v1.27.0-a #10
@ -1031,7 +1031,7 @@ workflows:
|
||||
requires:
|
||||
- build
|
||||
suite: utest-unit-rest
|
||||
target: "./blockstore/... ./build/... ./chain/... ./conformance/... ./gateway/... ./journal/... ./lib/... ./markets/... ./paychmgr/... ./provider/... ./tools/..."
|
||||
target: "./blockstore/... ./build/... ./chain/... ./conformance/... ./curiosrc/... ./gateway/... ./journal/... ./lib/... ./markets/... ./paychmgr/... ./tools/..."
|
||||
resource_class: 2xlarge
|
||||
- test:
|
||||
name: test-unit-storage
|
||||
|
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
@ -1,6 +1,3 @@
|
||||
# Reference
|
||||
# https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-code-owners
|
||||
|
||||
# Global owners
|
||||
# Ensure maintainers team is a requested reviewer for non-draft PRs
|
||||
* @jennijuju @Stebalien @snadrus @aarshkshah1992 @magik6k @zenground0 @arajasek @rjan90 @masih @rvagg
|
||||
|
248
.github/labels.yml
vendored
248
.github/labels.yml
vendored
@ -1,248 +0,0 @@
|
||||
###
|
||||
### Special magic GitHub labels
|
||||
### https://help.github.com/en/github/building-a-strong-community/encouraging-helpful-contributions-to-your-project-with-labels
|
||||
#
|
||||
- name: "good first issue"
|
||||
color: 7057ff
|
||||
description: "Good for newcomers"
|
||||
- name: "help wanted"
|
||||
color: 008672
|
||||
description: "Extra attention is needed"
|
||||
|
||||
###
|
||||
### Goals
|
||||
#
|
||||
- name: goal/incentives
|
||||
color: ff004d
|
||||
description: "Incentinet"
|
||||
|
||||
###
|
||||
### Areas
|
||||
#
|
||||
- name: area/ux
|
||||
color: 00A4E0
|
||||
description: "Area: UX"
|
||||
- name: area/chain/vm
|
||||
color: 00A4E2
|
||||
description: "Area: Chain/VM"
|
||||
- name: area/chain/sync
|
||||
color: 00A4E4
|
||||
description: "Area: Chain/Sync"
|
||||
- name: area/chain/misc
|
||||
color: 00A4E6
|
||||
description: "Area: Chain/Misc"
|
||||
- name: area/markets
|
||||
color: 00A4E8
|
||||
description: "Area: Markets"
|
||||
- name: area/sealing/fsm
|
||||
color: 0bb1ed
|
||||
description: "Area: Sealing/FSM"
|
||||
- name: area/sealing/storage
|
||||
color: 0EB4F0
|
||||
description: "Area: Sealing/Storage"
|
||||
- name: area/proving
|
||||
color: 0EB4F0
|
||||
description: "Area: Proving"
|
||||
- name: area/mining
|
||||
color: 10B6F2
|
||||
description: "Area: Mining"
|
||||
- name: area/client/storage
|
||||
color: 13B9F5
|
||||
description: "Area: Client/Storage"
|
||||
- name: area/client/retrieval
|
||||
color: 15BBF7
|
||||
description: "Area: Client/Retrieval"
|
||||
- name: area/wallet
|
||||
color: 15BBF7
|
||||
description: "Area: Wallet"
|
||||
- name: area/payment-channel
|
||||
color: ff6767
|
||||
description: "Area: Payment Channel"
|
||||
- name: area/multisig
|
||||
color: fff0ff
|
||||
description: "Area: Multisig"
|
||||
- name: area/networking
|
||||
color: 273f8a
|
||||
description: "Area: Networking"
|
||||
|
||||
###
|
||||
### Kinds
|
||||
#
|
||||
- name: kind/bug
|
||||
color: c92712
|
||||
description: "Kind: Bug"
|
||||
- name: kind/chore
|
||||
color: fcf0b5
|
||||
description: "Kind: Chore"
|
||||
- name: kind/feature
|
||||
color: FFF3B8
|
||||
description: "Kind: Feature"
|
||||
- name: kind/improvement
|
||||
color: FFF5BA
|
||||
description: "Kind: Improvement"
|
||||
- name: kind/test
|
||||
color: FFF8BD
|
||||
description: "Kind: Test"
|
||||
- name: kind/question
|
||||
color: FFFDC2
|
||||
description: "Kind: Question"
|
||||
- name: kind/enhancement
|
||||
color: FFFFC5
|
||||
description: "Kind: Enhancement"
|
||||
- name: kind/discussion
|
||||
color: FFFFC7
|
||||
description: "Kind: Discussion"
|
||||
|
||||
###
|
||||
### Difficulties
|
||||
#
|
||||
- name: dif/trivial
|
||||
color: b2b7ff
|
||||
description: "Can be confidently tackled by newcomers, who are widely unfamiliar with lotus"
|
||||
- name: dif/easy
|
||||
color: 7886d7
|
||||
description: "An existing lotus user should be able to pick this up"
|
||||
- name: dif/medium
|
||||
color: 6574cd
|
||||
description: "Prior development experience with lotus is likely helpful"
|
||||
- name: dif/hard
|
||||
color: 5661b3
|
||||
description: "Suggests that having worked on the specific component affected by this issue is important"
|
||||
- name: dif/expert
|
||||
color: 2f365f
|
||||
description: "Requires extensive knowledge of the history, implications, ramifications of the issue"
|
||||
|
||||
###
|
||||
### Efforts
|
||||
#
|
||||
- name: effort/minutes
|
||||
color: e8fffe
|
||||
description: "Effort: Minutes"
|
||||
- name: effort/hours
|
||||
color: a0f0ed
|
||||
description: "Effort: Hours"
|
||||
- name: effort/day
|
||||
color: 64d5ca
|
||||
description: "Effort: One Day"
|
||||
- name: effort/days
|
||||
color: 4dc0b5
|
||||
description: "Effort: Multiple Days"
|
||||
- name: effort/week
|
||||
color: 38a89d
|
||||
description: "Effort: One Week"
|
||||
- name: effort/weeks
|
||||
color: 20504f
|
||||
description: "Effort: Multiple Weeks"
|
||||
|
||||
###
|
||||
### Impacts
|
||||
#
|
||||
- name: impact/regression
|
||||
color: f1f5f8
|
||||
description: "Impact: Regression"
|
||||
- name: impact/api-breakage
|
||||
color: ECF0F3
|
||||
description: "Impact: API Breakage"
|
||||
- name: impact/quality
|
||||
color: E7EBEE
|
||||
description: "Impact: Quality"
|
||||
- name: impact/dx
|
||||
color: E2E6E9
|
||||
description: "Impact: Developer Experience"
|
||||
- name: impact/test-flakiness
|
||||
color: DDE1E4
|
||||
description: "Impact: Test Flakiness"
|
||||
- name: impact/consensus
|
||||
color: b20014
|
||||
description: "Impact: Consensus"
|
||||
|
||||
###
|
||||
### Topics
|
||||
#
|
||||
- name: topic/interoperability
|
||||
color: bf0f73
|
||||
description: "Topic: Interoperability"
|
||||
- name: topic/specs
|
||||
color: CC1C80
|
||||
description: "Topic: Specs"
|
||||
- name: topic/docs
|
||||
color: D9298D
|
||||
description: "Topic: Documentation"
|
||||
- name: topic/architecture
|
||||
color: E53599
|
||||
description: "Topic: Architecture"
|
||||
|
||||
###
|
||||
### Priorities
|
||||
###
|
||||
- name: P0
|
||||
color: dd362a
|
||||
description: "P0: Critical Blocker"
|
||||
- name: P1
|
||||
color: ce8048
|
||||
description: "P1: Must be resolved"
|
||||
- name: P2
|
||||
color: dbd81a
|
||||
description: "P2: Should be resolved"
|
||||
- name: P3
|
||||
color: 9fea8f
|
||||
description: "P3: Might get resolved"
|
||||
|
||||
###
|
||||
### Hints
|
||||
#
|
||||
#- name: hint/good-first-issue
|
||||
# color: 7057ff
|
||||
# description: "Hint: Good First Issue"
|
||||
#- name: hint/help-wanted
|
||||
# color: 008672
|
||||
# description: "Hint: Help Wanted"
|
||||
- name: hint/needs-decision
|
||||
color: 33B9A5
|
||||
description: "Hint: Needs Decision"
|
||||
- name: hint/needs-triage
|
||||
color: 1AA08C
|
||||
description: "Hint: Needs Triage"
|
||||
- name: hint/needs-analysis
|
||||
color: 26AC98
|
||||
description: "Hint: Needs Analysis"
|
||||
- name: hint/needs-author-input
|
||||
color: 33B9A5
|
||||
description: "Hint: Needs Author Input"
|
||||
- name: hint/needs-team-input
|
||||
color: 40C6B2
|
||||
description: "Hint: Needs Team Input"
|
||||
- name: hint/needs-community-input
|
||||
color: 4DD3BF
|
||||
description: "Hint: Needs Community Input"
|
||||
- name: hint/needs-review
|
||||
color: 5AE0CC
|
||||
description: "Hint: Needs Review"
|
||||
|
||||
###
|
||||
### Statuses
|
||||
#
|
||||
- name: status/done
|
||||
color: edb3a6
|
||||
description: "Status: Done"
|
||||
- name: status/deferred
|
||||
color: E0A699
|
||||
description: "Status: Deferred"
|
||||
- name: status/in-progress
|
||||
color: D49A8D
|
||||
description: "Status: In Progress"
|
||||
- name: status/blocked
|
||||
color: C78D80
|
||||
description: "Status: Blocked"
|
||||
- name: status/inactive
|
||||
color: BA8073
|
||||
description: "Status: Inactive"
|
||||
- name: status/waiting
|
||||
color: AD7366
|
||||
description: "Status: Waiting"
|
||||
- name: status/rotten
|
||||
color: 7A4033
|
||||
description: "Status: Rotten"
|
||||
- name: status/discarded
|
||||
color: 6D3326
|
||||
description: "Status: Discarded / Won't fix"
|
4
.github/workflows/builtin-actor-tests.yml
vendored
4
.github/workflows/builtin-actor-tests.yml
vendored
@ -11,8 +11,8 @@ jobs:
|
||||
name: Release Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21
|
||||
- run: go test -tags=release ./build
|
73
.github/workflows/codeql-analysis.yml
vendored
73
.github/workflows/codeql-analysis.yml
vendored
@ -1,73 +0,0 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- 'release/*'
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches:
|
||||
- master
|
||||
- 'release/*'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'go' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.18.8'
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: go
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
17
.github/workflows/label-syncer.yml
vendored
17
.github/workflows/label-syncer.yml
vendored
@ -1,17 +0,0 @@
|
||||
|
||||
name: Label syncer
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '.github/labels.yml'
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
build:
|
||||
name: Sync labels
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@1.0.0
|
||||
- uses: micnncim/action-label-syncer@v1.0.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
6
.github/workflows/stale.yml
vendored
6
.github/workflows/stale.yml
vendored
@ -13,9 +13,9 @@ jobs:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repo-token: ${{ github.token }}
|
||||
stale-issue-message: 'Oops, seems like we needed more information for this issue, please comment with more details or this issue will be closed in 24 hours.'
|
||||
close-issue-message: 'This issue was closed because it is missing author input.'
|
||||
stale-pr-message: 'Thank you for submitting the PR and contributing to lotus! Lotus maintainers need more of your input before merging it, please address the suggested changes or reply to the comments or this PR will be closed in 48 hours. You are always more than welcome to reopen the PR later as well!'
|
||||
@ -29,5 +29,3 @@ jobs:
|
||||
days-before-pr-close: 2
|
||||
remove-stale-when-updated: true
|
||||
enable-statistics: true
|
||||
|
||||
|
||||
|
2
.github/workflows/sync-master-main.yaml
vendored
2
.github/workflows/sync-master-main.yaml
vendored
@ -7,7 +7,7 @@ jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: update remote branch main
|
||||
run: |
|
||||
# overrides the remote branch (origin:github) `main`
|
||||
|
29
.github/workflows/testground-on-push.yml
vendored
29
.github/workflows/testground-on-push.yml
vendored
@ -1,29 +0,0 @@
|
||||
---
|
||||
name: Testground PR Checker
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
testground:
|
||||
runs-on: ubuntu-latest
|
||||
name: ${{ matrix.composition_file }}
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- backend_addr: ci.testground.ipfs.team
|
||||
backend_proto: https
|
||||
plan_directory: testplans/lotus-soup
|
||||
composition_file: testplans/lotus-soup/_compositions/baseline-k8s-3-1.toml
|
||||
- backend_addr: ci.testground.ipfs.team
|
||||
backend_proto: https
|
||||
plan_directory: testplans/lotus-soup
|
||||
composition_file: testplans/lotus-soup/_compositions/paych-stress-k8s.toml
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: testground run
|
||||
uses: testground/testground-github-action@v1
|
||||
with:
|
||||
backend_addr: ${{ matrix.backend_addr }}
|
||||
backend_proto: ${{ matrix.backend_proto }}
|
||||
plan_directory: ${{ matrix.plan_directory }}
|
||||
composition_file: ${{ matrix.composition_file }}
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -6,7 +6,7 @@
|
||||
/lotus-chainwatch
|
||||
/lotus-shed
|
||||
/lotus-sim
|
||||
/lotus-provider
|
||||
/curio
|
||||
/lotus-townhall
|
||||
/lotus-fountain
|
||||
/lotus-stats
|
||||
@ -36,6 +36,9 @@ build/paramfetch.sh
|
||||
/darwin
|
||||
/linux
|
||||
*.snap
|
||||
curio
|
||||
devgen.car
|
||||
localnet.json
|
||||
|
||||
*-fuzz.zip
|
||||
/chain/types/work_msg/
|
||||
|
15
CHANGELOG.md
15
CHANGELOG.md
@ -3,6 +3,7 @@
|
||||
# UNRELEASED
|
||||
|
||||
## New features
|
||||
- feat: CLI: add claim-extend cli (#11711) ([filecoin-project/lotus#11711](https://github.com/filecoin-project/lotus/pull/11711))
|
||||
|
||||
## Improvements
|
||||
|
||||
@ -132,20 +133,22 @@ Additionally, Filecoin is not Ethereum no matter how much we try to provide API/
|
||||
|
||||
[handlefilecoinmethod]: https://fips.filecoin.io/FIPS/fip-0054.html#handlefilecoinmethod-general-handler-for-method-numbers--1024
|
||||
|
||||
### GetActorEvents and SubscribeActorEvents
|
||||
### GetActorEventsRaw and SubscribeActorEventsRaw
|
||||
|
||||
[FIP-0049](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0049.md) introduced _Actor Events_ that can be emitted by user programmed actors. [FIP-0083](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0083.md) introduces new events emitted by the builtin Verified Registry, Miner and Market Actors. These new events for builtin actors are being activated with network version 22 to coincide with _Direct Data Onboarding_ as defined in [FIP-0076](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0076.md) which introduces additional flexibility for data onboarding. Sector, Deal and DataCap lifecycles can be tracked with these events, providing visibility and options for programmatic responses to changes in state.
|
||||
|
||||
Actor events are available on message receipts, but can now be retrieved from a node using the new `GetActorEvents` and `SubscribeActorEvents` methods. These methods allow for querying and subscribing to actor events, respectively. They depend on the Lotus node both collecting events (with `Fevm.Events.RealTimeFilterAPI` and `Fevm.Events.HistoricFilterAPI`) and being enabled with the new configuration option `Events.EnableActorEventsAPI`. Note that a Lotus node can only respond to requests for historic events that it retains in its event store.
|
||||
Actor events are available on message receipts, but can now be retrieved from a node using the new `GetActorEventsRaw` and `SubscribeActorEventsRaw` methods. These methods allow for querying and subscribing to actor events, respectively. They depend on the Lotus node both collecting events (with `Fevm.Events.RealTimeFilterAPI` and `Fevm.Events.HistoricFilterAPI`) and being enabled with the new configuration option `Events.EnableActorEventsAPI`. Note that a Lotus node can only respond to requests for historic events that it retains in its event store.
|
||||
|
||||
Both `GetActorEvents` and `SubscribeActorEvents` take a filter parameter which can optionally filter events on:
|
||||
Both `GetActorEventsRaw` and `SubscribeActorEventsRaw` take a filter parameter which can optionally filter events on:
|
||||
|
||||
* `Addresses` of the actor(s) emitting the event
|
||||
* Specific `Fields` within the event
|
||||
* `FromHeight` and `ToHeight` to filter events by block height
|
||||
* `TipSetKey` to restrict events contained within a specific tipset
|
||||
|
||||
`GetActorEvents` provides a one-time query for actor events, while `SubscribeActorEvents` provides a long-lived connection (via websockets) to the Lotus node, allowing for real-time updates on actor events. The subscription can be cancelled by the client at any time.
|
||||
`GetActorEventsRaw` provides a one-time query for actor events, while `SubscribeActorEventsRaw` provides a long-lived connection (via websockets) to the Lotus node, allowing for real-time updates on actor events. The subscription can be cancelled by the client at any time.
|
||||
|
||||
A future Lotus release may include `GetActorEvents` and `SubscribeActorEvents` methods which will provide a more user-friendly interface to actor events, including deserialization of event data.
|
||||
|
||||
### GetAllClaims and GetAllAlocations
|
||||
Additionally the methods `GetAllAllocations` and `GetAllClaims` has been added to the Lotus API. These methods lists all the available allocations and claims available in the actor state.
|
||||
@ -3691,7 +3694,7 @@ This is a **highly recommended** but optional Lotus v1.11.1 release that introd
|
||||
- Config for deal publishing control addresses ([filecoin-project/lotus#6697](https://github.com/filecoin-project/lotus/pull/6697))
|
||||
- Set `DealPublishControl` to set the wallet used for sending `PublishStorageDeals` messages, instructions [here](https://lotus.filecoin.io/storage-providers/operate/addresses/#control-addresses).
|
||||
- Config UX improvements ([filecoin-project/lotus#6848](https://github.com/filecoin-project/lotus/pull/6848))
|
||||
- You can now preview the the default and updated node config by running `lotus/lotus-miner config default/updated`
|
||||
- You can now preview the default and updated node config by running `lotus/lotus-miner config default/updated`
|
||||
|
||||
## New Features
|
||||
- ⭐️⭐️⭐️ Support standalone miner-market process ([filecoin-project/lotus#6356](https://github.com/filecoin-project/lotus/pull/6356))
|
||||
@ -5138,7 +5141,7 @@ This consensus-breaking release of Lotus upgrades the actors version to v2.0.0.
|
||||
|
||||
#### Mining
|
||||
|
||||
- Increased ExpectedSealDuration and and WaitDealsDelay (https://github.com/filecoin-project/lotus/pull/3743)
|
||||
- Increased ExpectedSealDuration and WaitDealsDelay (https://github.com/filecoin-project/lotus/pull/3743)
|
||||
- Miner backup/restore commands (https://github.com/filecoin-project/lotus/pull/4133)
|
||||
- lotus-miner: add more help text to storage / attach (https://github.com/filecoin-project/lotus/pull/3961)
|
||||
- Reject deals that are > 7 days in the future in the BasicDealFilter (https://github.com/filecoin-project/lotus/pull/4173)
|
||||
|
@ -109,7 +109,7 @@ COPY --from=lotus-builder /opt/filecoin/lotus-wallet /usr/local/bin/
|
||||
COPY --from=lotus-builder /opt/filecoin/lotus-gateway /usr/local/bin/
|
||||
COPY --from=lotus-builder /opt/filecoin/lotus-miner /usr/local/bin/
|
||||
COPY --from=lotus-builder /opt/filecoin/lotus-worker /usr/local/bin/
|
||||
COPY --from=lotus-builder /opt/filecoin/lotus-provider /usr/local/bin/
|
||||
COPY --from=lotus-builder /opt/filecoin/curio /usr/local/bin/
|
||||
COPY --from=lotus-builder /opt/filecoin/lotus-stats /usr/local/bin/
|
||||
COPY --from=lotus-builder /opt/filecoin/lotus-fountain /usr/local/bin/
|
||||
|
||||
@ -118,13 +118,13 @@ RUN mkdir /var/lib/lotus
|
||||
RUN mkdir /var/lib/lotus-miner
|
||||
RUN mkdir /var/lib/lotus-worker
|
||||
RUN mkdir /var/lib/lotus-wallet
|
||||
RUN mkdir /var/lib/lotus-provider
|
||||
RUN mkdir /var/lib/curio
|
||||
RUN chown fc: /var/tmp/filecoin-proof-parameters
|
||||
RUN chown fc: /var/lib/lotus
|
||||
RUN chown fc: /var/lib/lotus-miner
|
||||
RUN chown fc: /var/lib/lotus-worker
|
||||
RUN chown fc: /var/lib/lotus-wallet
|
||||
RUN chown fc: /var/lib/lotus-provider
|
||||
RUN chown fc: /var/lib/curio
|
||||
|
||||
|
||||
VOLUME /var/tmp/filecoin-proof-parameters
|
||||
@ -132,7 +132,7 @@ VOLUME /var/lib/lotus
|
||||
VOLUME /var/lib/lotus-miner
|
||||
VOLUME /var/lib/lotus-worker
|
||||
VOLUME /var/lib/lotus-wallet
|
||||
VOLUME /var/lib/lotus-provider
|
||||
VOLUME /var/lib/curio
|
||||
|
||||
EXPOSE 1234
|
||||
EXPOSE 2345
|
||||
|
60
Makefile
60
Makefile
@ -66,7 +66,7 @@ CLEAN+=build/.update-modules
|
||||
deps: $(BUILD_DEPS)
|
||||
.PHONY: deps
|
||||
|
||||
build-devnets: build lotus-seed lotus-shed lotus-provider
|
||||
build-devnets: build lotus-seed lotus-shed curio
|
||||
.PHONY: build-devnets
|
||||
|
||||
debug: GOFLAGS+=-tags=debug
|
||||
@ -97,14 +97,14 @@ lotus-miner: $(BUILD_DEPS)
|
||||
.PHONY: lotus-miner
|
||||
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
|
||||
curio: $(BUILD_DEPS)
|
||||
rm -f curio
|
||||
$(GOCC) build $(GOFLAGS) -o curio ./cmd/curio
|
||||
.PHONY: curio
|
||||
BINS+=curio
|
||||
|
||||
lp2k: GOFLAGS+=-tags=2k
|
||||
lp2k: lotus-provider
|
||||
cu2k: GOFLAGS+=-tags=2k
|
||||
cu2k: curio
|
||||
|
||||
lotus-worker: $(BUILD_DEPS)
|
||||
rm -f lotus-worker
|
||||
@ -124,13 +124,13 @@ lotus-gateway: $(BUILD_DEPS)
|
||||
.PHONY: lotus-gateway
|
||||
BINS+=lotus-gateway
|
||||
|
||||
build: lotus lotus-miner lotus-worker lotus-provider
|
||||
build: lotus lotus-miner lotus-worker curio
|
||||
@[[ $$(type -P "lotus") ]] && echo "Caution: you have \
|
||||
an existing lotus binary in your PATH. This may cause problems if you don't run 'sudo make install'" || true
|
||||
|
||||
.PHONY: build
|
||||
|
||||
install: install-daemon install-miner install-worker install-provider
|
||||
install: install-daemon install-miner install-worker install-curio
|
||||
|
||||
install-daemon:
|
||||
install -C ./lotus /usr/local/bin/lotus
|
||||
@ -138,8 +138,8 @@ install-daemon:
|
||||
install-miner:
|
||||
install -C ./lotus-miner /usr/local/bin/lotus-miner
|
||||
|
||||
install-provider:
|
||||
install -C ./lotus-provider /usr/local/bin/lotus-provider
|
||||
install-curio:
|
||||
install -C ./curio /usr/local/bin/curio
|
||||
|
||||
install-worker:
|
||||
install -C ./lotus-worker /usr/local/bin/lotus-worker
|
||||
@ -156,8 +156,8 @@ uninstall-daemon:
|
||||
uninstall-miner:
|
||||
rm -f /usr/local/bin/lotus-miner
|
||||
|
||||
uninstall-provider:
|
||||
rm -f /usr/local/bin/lotus-provider
|
||||
uninstall-curio:
|
||||
rm -f /usr/local/bin/curio
|
||||
|
||||
uninstall-worker:
|
||||
rm -f /usr/local/bin/lotus-worker
|
||||
@ -260,13 +260,13 @@ install-miner-service: install-miner install-daemon-service
|
||||
@echo "To start the service, run: 'sudo systemctl start lotus-miner'"
|
||||
@echo "To enable the service on startup, run: 'sudo systemctl enable lotus-miner'"
|
||||
|
||||
install-provider-service: install-provider install-daemon-service
|
||||
install-curio-service: install-curio install-daemon-service
|
||||
mkdir -p /etc/systemd/system
|
||||
mkdir -p /var/log/lotus
|
||||
install -C -m 0644 ./scripts/lotus-provider.service /etc/systemd/system/lotus-provider.service
|
||||
install -C -m 0644 ./scripts/curio.service /etc/systemd/system/curio.service
|
||||
systemctl daemon-reload
|
||||
@echo
|
||||
@echo "lotus-provider service installed. Don't forget to run 'sudo systemctl start lotus-provider' to start it and 'sudo systemctl enable lotus-provider' for it to be enabled on startup."
|
||||
@echo "Curio service installed. Don't forget to run 'sudo systemctl start curio' to start it and 'sudo systemctl enable curio' for it to be enabled on startup."
|
||||
|
||||
install-main-services: install-miner-service
|
||||
|
||||
@ -286,10 +286,10 @@ clean-miner-service:
|
||||
rm -f /etc/systemd/system/lotus-miner.service
|
||||
systemctl daemon-reload
|
||||
|
||||
clean-provider-service:
|
||||
-systemctl stop lotus-provider
|
||||
-systemctl disable lotus-provider
|
||||
rm -f /etc/systemd/system/lotus-provider.service
|
||||
clean-curio-service:
|
||||
-systemctl stop curio
|
||||
-systemctl disable curio
|
||||
rm -f /etc/systemd/system/curio.service
|
||||
systemctl daemon-reload
|
||||
|
||||
clean-main-services: clean-daemon-service
|
||||
@ -332,7 +332,7 @@ actors-code-gen:
|
||||
$(GOCC) fmt ./...
|
||||
|
||||
actors-gen: actors-code-gen
|
||||
./scripts/fiximports
|
||||
$(GOCC) run ./scripts/fiximports
|
||||
.PHONY: actors-gen
|
||||
|
||||
bundle-gen:
|
||||
@ -366,7 +366,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-provider
|
||||
docsgen-md: docsgen-md-full docsgen-md-storage docsgen-md-worker docsgen-md-curio
|
||||
|
||||
docsgen-md-full: docsgen-md-bin
|
||||
./docgen-md "api/api_full.go" "FullNode" "api" "./api" > documentation/en/api-v1-unstable-methods.md
|
||||
@ -375,8 +375,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-md-curio: docsgen-md-bin
|
||||
./docgen-md "api/api_curio.go" "Curio" "api" "./api" > documentation/en/api-v0-methods-curio.md
|
||||
|
||||
docsgen-openrpc: docsgen-openrpc-full docsgen-openrpc-storage docsgen-openrpc-worker docsgen-openrpc-gateway
|
||||
|
||||
@ -392,25 +392,25 @@ docsgen-openrpc-gateway: docsgen-openrpc-bin
|
||||
.PHONY: docsgen docsgen-md-bin docsgen-openrpc-bin
|
||||
|
||||
fiximports:
|
||||
./scripts/fiximports
|
||||
$(GOCC) run ./scripts/fiximports
|
||||
|
||||
gen: actors-code-gen type-gen cfgdoc-gen docsgen api-gen circleci
|
||||
./scripts/fiximports
|
||||
$(GOCC) run ./scripts/fiximports
|
||||
@echo ">>> IF YOU'VE MODIFIED THE CLI OR CONFIG, REMEMBER TO ALSO RUN 'make docsgen-cli'"
|
||||
.PHONY: gen
|
||||
|
||||
jen: gen
|
||||
|
||||
snap: lotus lotus-miner lotus-worker lotus-provider
|
||||
snap: lotus lotus-miner lotus-worker curio
|
||||
snapcraft
|
||||
# snapcraft upload ./lotus_*.snap
|
||||
|
||||
# separate from gen because it needs binaries
|
||||
docsgen-cli: lotus lotus-miner lotus-worker lotus-provider
|
||||
docsgen-cli: lotus lotus-miner lotus-worker curio
|
||||
python3 ./scripts/generate-lotus-cli.py
|
||||
./lotus config default > documentation/en/default-lotus-config.toml
|
||||
./lotus-miner config default > documentation/en/default-lotus-miner-config.toml
|
||||
./lotus-provider config default > documentation/en/default-lotus-provider-config.toml
|
||||
./curio config default > documentation/en/default-curio-config.toml
|
||||
.PHONY: docsgen-cli
|
||||
|
||||
print-%:
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
|
||||
type LotusProvider interface {
|
||||
type Curio interface {
|
||||
Version(context.Context) (Version, error) //perm:admin
|
||||
|
||||
AllocatePieceToSector(ctx context.Context, maddr address.Address, piece PieceDealInfo, rawSize int64, source url.URL, header http.Header) (SectorOffset, error) //perm:write
|
@ -906,16 +906,16 @@ type FullNode interface {
|
||||
|
||||
// Actor events
|
||||
|
||||
// GetActorEvents returns all user-programmed and built-in actor events that match the given
|
||||
// GetActorEventsRaw returns all user-programmed and built-in actor events that match the given
|
||||
// filter.
|
||||
// This is a request/response API.
|
||||
// Results available from this API may be limited by the MaxFilterResults and MaxFilterHeightRange
|
||||
// configuration options and also the amount of historical data available in the node.
|
||||
//
|
||||
// This is an EXPERIMENTAL API and may be subject to change.
|
||||
GetActorEvents(ctx context.Context, filter *types.ActorEventFilter) ([]*types.ActorEvent, error) //perm:read
|
||||
GetActorEventsRaw(ctx context.Context, filter *types.ActorEventFilter) ([]*types.ActorEvent, error) //perm:read
|
||||
|
||||
// SubscribeActorEvents returns a long-lived stream of all user-programmed and built-in actor
|
||||
// SubscribeActorEventsRaw returns a long-lived stream of all user-programmed and built-in actor
|
||||
// events that match the given filter.
|
||||
// Events that match the given filter are written to the stream in real-time as they are emitted
|
||||
// from the FVM.
|
||||
@ -929,7 +929,7 @@ type FullNode interface {
|
||||
//
|
||||
// Note: this API is only available via websocket connections.
|
||||
// This is an EXPERIMENTAL API and may be subject to change.
|
||||
SubscribeActorEvents(ctx context.Context, filter *types.ActorEventFilter) (<-chan *types.ActorEvent, error) //perm:read
|
||||
SubscribeActorEventsRaw(ctx context.Context, filter *types.ActorEventFilter) (<-chan *types.ActorEvent, error) //perm:read
|
||||
}
|
||||
|
||||
// reverse interface to the client, called after EthSubscribe
|
||||
|
@ -77,6 +77,7 @@ type Gateway interface {
|
||||
StateMarketBalance(ctx context.Context, addr address.Address, tsk types.TipSetKey) (MarketBalance, error)
|
||||
StateMarketStorageDeal(ctx context.Context, dealId abi.DealID, tsk types.TipSetKey) (*MarketDeal, error)
|
||||
StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (MinerInfo, error)
|
||||
StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]Deadline, error)
|
||||
StateMinerProvingDeadline(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*dline.Info, error)
|
||||
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
|
||||
StateNetworkName(context.Context) (dtypes.NetworkName, error)
|
||||
@ -130,6 +131,7 @@ type Gateway interface {
|
||||
EthTraceBlock(ctx context.Context, blkNum string) ([]*ethtypes.EthTraceBlock, error)
|
||||
EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error)
|
||||
|
||||
GetActorEvents(ctx context.Context, filter *types.ActorEventFilter) ([]*types.ActorEvent, error)
|
||||
SubscribeActorEvents(ctx context.Context, filter *types.ActorEventFilter) (<-chan *types.ActorEvent, error)
|
||||
GetActorEventsRaw(ctx context.Context, filter *types.ActorEventFilter) ([]*types.ActorEvent, error)
|
||||
SubscribeActorEventsRaw(ctx context.Context, filter *types.ActorEventFilter) (<-chan *types.ActorEvent, error)
|
||||
ChainGetEvents(context.Context, cid.Cid) ([]types.Event, error)
|
||||
}
|
||||
|
@ -15,9 +15,9 @@ import (
|
||||
"github.com/filecoin-project/lotus/lib/rpcenc"
|
||||
)
|
||||
|
||||
// NewProviderRpc creates a new http jsonrpc client.
|
||||
func NewProviderRpc(ctx context.Context, addr string, requestHeader http.Header) (api.LotusProvider, jsonrpc.ClientCloser, error) {
|
||||
var res v1api.LotusProviderStruct
|
||||
// NewCurioRpc creates a new http jsonrpc client.
|
||||
func NewCurioRpc(ctx context.Context, addr string, requestHeader http.Header) (api.Curio, jsonrpc.ClientCloser, error) {
|
||||
var res v1api.CurioStruct
|
||||
|
||||
closer, err := jsonrpc.NewMergeClient(ctx, addr, "Filecoin",
|
||||
api.GetInternalStructs(&res), requestHeader, jsonrpc.WithErrors(api.RPCErrors))
|
||||
|
@ -456,10 +456,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))
|
||||
case "Curio":
|
||||
i = &api.CurioStruct{}
|
||||
t = reflect.TypeOf(new(struct{ api.Curio })).Elem()
|
||||
permStruct = append(permStruct, reflect.TypeOf(api.CurioStruct{}.Internal))
|
||||
default:
|
||||
panic("unknown type")
|
||||
}
|
||||
|
@ -1627,19 +1627,19 @@ func (mr *MockFullNodeMockRecorder) GasEstimateMessageGas(arg0, arg1, arg2, arg3
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GasEstimateMessageGas", reflect.TypeOf((*MockFullNode)(nil).GasEstimateMessageGas), arg0, arg1, arg2, arg3)
|
||||
}
|
||||
|
||||
// GetActorEvents mocks base method.
|
||||
func (m *MockFullNode) GetActorEvents(arg0 context.Context, arg1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {
|
||||
// GetActorEventsRaw mocks base method.
|
||||
func (m *MockFullNode) GetActorEventsRaw(arg0 context.Context, arg1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetActorEvents", arg0, arg1)
|
||||
ret := m.ctrl.Call(m, "GetActorEventsRaw", arg0, arg1)
|
||||
ret0, _ := ret[0].([]*types.ActorEvent)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetActorEvents indicates an expected call of GetActorEvents.
|
||||
func (mr *MockFullNodeMockRecorder) GetActorEvents(arg0, arg1 interface{}) *gomock.Call {
|
||||
// GetActorEventsRaw indicates an expected call of GetActorEventsRaw.
|
||||
func (mr *MockFullNodeMockRecorder) GetActorEventsRaw(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetActorEvents", reflect.TypeOf((*MockFullNode)(nil).GetActorEvents), arg0, arg1)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetActorEventsRaw", reflect.TypeOf((*MockFullNode)(nil).GetActorEventsRaw), arg0, arg1)
|
||||
}
|
||||
|
||||
// ID mocks base method.
|
||||
@ -3954,19 +3954,19 @@ func (mr *MockFullNodeMockRecorder) StateWaitMsg(arg0, arg1, arg2, arg3, arg4 in
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateWaitMsg", reflect.TypeOf((*MockFullNode)(nil).StateWaitMsg), arg0, arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
// SubscribeActorEvents mocks base method.
|
||||
func (m *MockFullNode) SubscribeActorEvents(arg0 context.Context, arg1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) {
|
||||
// SubscribeActorEventsRaw mocks base method.
|
||||
func (m *MockFullNode) SubscribeActorEventsRaw(arg0 context.Context, arg1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SubscribeActorEvents", arg0, arg1)
|
||||
ret := m.ctrl.Call(m, "SubscribeActorEventsRaw", arg0, arg1)
|
||||
ret0, _ := ret[0].(<-chan *types.ActorEvent)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SubscribeActorEvents indicates an expected call of SubscribeActorEvents.
|
||||
func (mr *MockFullNodeMockRecorder) SubscribeActorEvents(arg0, arg1 interface{}) *gomock.Call {
|
||||
// SubscribeActorEventsRaw indicates an expected call of SubscribeActorEventsRaw.
|
||||
func (mr *MockFullNodeMockRecorder) SubscribeActorEventsRaw(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeActorEvents", reflect.TypeOf((*MockFullNode)(nil).SubscribeActorEvents), arg0, arg1)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeActorEventsRaw", reflect.TypeOf((*MockFullNode)(nil).SubscribeActorEventsRaw), arg0, arg1)
|
||||
}
|
||||
|
||||
// SyncCheckBad mocks base method.
|
||||
|
346
api/proxy_gen.go
346
api/proxy_gen.go
@ -115,6 +115,35 @@ type CommonNetStub struct {
|
||||
NetStub
|
||||
}
|
||||
|
||||
type CurioStruct struct {
|
||||
Internal CurioMethods
|
||||
}
|
||||
|
||||
type CurioMethods struct {
|
||||
AllocatePieceToSector func(p0 context.Context, p1 address.Address, p2 PieceDealInfo, p3 int64, p4 url.URL, p5 http.Header) (SectorOffset, error) `perm:"write"`
|
||||
|
||||
Shutdown func(p0 context.Context) error `perm:"admin"`
|
||||
|
||||
StorageAddLocal func(p0 context.Context, p1 string) error `perm:"admin"`
|
||||
|
||||
StorageDetachLocal func(p0 context.Context, p1 string) error `perm:"admin"`
|
||||
|
||||
StorageFindSector func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 abi.SectorSize, p4 bool) ([]storiface.SectorStorageInfo, error) `perm:"admin"`
|
||||
|
||||
StorageInfo func(p0 context.Context, p1 storiface.ID) (storiface.StorageInfo, error) `perm:"admin"`
|
||||
|
||||
StorageList func(p0 context.Context) (map[storiface.ID][]storiface.Decl, error) `perm:"admin"`
|
||||
|
||||
StorageLocal func(p0 context.Context) (map[storiface.ID]string, error) `perm:"admin"`
|
||||
|
||||
StorageStat func(p0 context.Context, p1 storiface.ID) (fsutil.FsStat, error) `perm:"admin"`
|
||||
|
||||
Version func(p0 context.Context) (Version, error) `perm:"admin"`
|
||||
}
|
||||
|
||||
type CurioStub struct {
|
||||
}
|
||||
|
||||
type EthSubscriberStruct struct {
|
||||
Internal EthSubscriberMethods
|
||||
}
|
||||
@ -337,7 +366,7 @@ type FullNodeMethods struct {
|
||||
|
||||
GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) `perm:"read"`
|
||||
|
||||
GetActorEvents func(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) `perm:"read"`
|
||||
GetActorEventsRaw func(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) `perm:"read"`
|
||||
|
||||
MarketAddBalance func(p0 context.Context, p1 address.Address, p2 address.Address, p3 types.BigInt) (cid.Cid, error) `perm:"sign"`
|
||||
|
||||
@ -589,7 +618,7 @@ type FullNodeMethods struct {
|
||||
|
||||
StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"`
|
||||
|
||||
SubscribeActorEvents func(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) `perm:"read"`
|
||||
SubscribeActorEventsRaw func(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) `perm:"read"`
|
||||
|
||||
SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"`
|
||||
|
||||
@ -653,6 +682,8 @@ type GatewayMethods struct {
|
||||
|
||||
ChainGetBlockMessages func(p0 context.Context, p1 cid.Cid) (*BlockMessages, error) ``
|
||||
|
||||
ChainGetEvents func(p0 context.Context, p1 cid.Cid) ([]types.Event, error) ``
|
||||
|
||||
ChainGetGenesis func(p0 context.Context) (*types.TipSet, error) ``
|
||||
|
||||
ChainGetMessage func(p0 context.Context, p1 cid.Cid) (*types.Message, error) ``
|
||||
@ -757,7 +788,7 @@ type GatewayMethods struct {
|
||||
|
||||
GasEstimateMessageGas func(p0 context.Context, p1 *types.Message, p2 *MessageSendSpec, p3 types.TipSetKey) (*types.Message, error) ``
|
||||
|
||||
GetActorEvents func(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) ``
|
||||
GetActorEventsRaw func(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) ``
|
||||
|
||||
MinerGetBaseInfo func(p0 context.Context, p1 address.Address, p2 abi.ChainEpoch, p3 types.TipSetKey) (*MiningBaseInfo, error) ``
|
||||
|
||||
@ -807,6 +838,8 @@ type GatewayMethods struct {
|
||||
|
||||
StateMarketStorageDeal func(p0 context.Context, p1 abi.DealID, p2 types.TipSetKey) (*MarketDeal, error) ``
|
||||
|
||||
StateMinerDeadlines func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]Deadline, error) ``
|
||||
|
||||
StateMinerInfo func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerInfo, error) ``
|
||||
|
||||
StateMinerPower func(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (*MinerPower, error) ``
|
||||
@ -833,7 +866,7 @@ type GatewayMethods struct {
|
||||
|
||||
StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) ``
|
||||
|
||||
SubscribeActorEvents func(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) ``
|
||||
SubscribeActorEventsRaw func(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) ``
|
||||
|
||||
Version func(p0 context.Context) (APIVersion, error) ``
|
||||
|
||||
@ -845,35 +878,6 @@ type GatewayMethods struct {
|
||||
type GatewayStub struct {
|
||||
}
|
||||
|
||||
type LotusProviderStruct struct {
|
||||
Internal LotusProviderMethods
|
||||
}
|
||||
|
||||
type LotusProviderMethods struct {
|
||||
AllocatePieceToSector func(p0 context.Context, p1 address.Address, p2 PieceDealInfo, p3 int64, p4 url.URL, p5 http.Header) (SectorOffset, error) `perm:"write"`
|
||||
|
||||
Shutdown func(p0 context.Context) error `perm:"admin"`
|
||||
|
||||
StorageAddLocal func(p0 context.Context, p1 string) error `perm:"admin"`
|
||||
|
||||
StorageDetachLocal func(p0 context.Context, p1 string) error `perm:"admin"`
|
||||
|
||||
StorageFindSector func(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 abi.SectorSize, p4 bool) ([]storiface.SectorStorageInfo, error) `perm:"admin"`
|
||||
|
||||
StorageInfo func(p0 context.Context, p1 storiface.ID) (storiface.StorageInfo, error) `perm:"admin"`
|
||||
|
||||
StorageList func(p0 context.Context) (map[storiface.ID][]storiface.Decl, error) `perm:"admin"`
|
||||
|
||||
StorageLocal func(p0 context.Context) (map[storiface.ID]string, error) `perm:"admin"`
|
||||
|
||||
StorageStat func(p0 context.Context, p1 storiface.ID) (fsutil.FsStat, error) `perm:"admin"`
|
||||
|
||||
Version func(p0 context.Context) (Version, error) `perm:"admin"`
|
||||
}
|
||||
|
||||
type LotusProviderStub struct {
|
||||
}
|
||||
|
||||
type NetStruct struct {
|
||||
Internal NetMethods
|
||||
}
|
||||
@ -1484,6 +1488,116 @@ func (s *CommonStub) Version(p0 context.Context) (APIVersion, error) {
|
||||
return *new(APIVersion), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *CurioStruct) AllocatePieceToSector(p0 context.Context, p1 address.Address, p2 PieceDealInfo, p3 int64, p4 url.URL, p5 http.Header) (SectorOffset, error) {
|
||||
if s.Internal.AllocatePieceToSector == nil {
|
||||
return *new(SectorOffset), ErrNotSupported
|
||||
}
|
||||
return s.Internal.AllocatePieceToSector(p0, p1, p2, p3, p4, p5)
|
||||
}
|
||||
|
||||
func (s *CurioStub) AllocatePieceToSector(p0 context.Context, p1 address.Address, p2 PieceDealInfo, p3 int64, p4 url.URL, p5 http.Header) (SectorOffset, error) {
|
||||
return *new(SectorOffset), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *CurioStruct) Shutdown(p0 context.Context) error {
|
||||
if s.Internal.Shutdown == nil {
|
||||
return ErrNotSupported
|
||||
}
|
||||
return s.Internal.Shutdown(p0)
|
||||
}
|
||||
|
||||
func (s *CurioStub) Shutdown(p0 context.Context) error {
|
||||
return ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *CurioStruct) StorageAddLocal(p0 context.Context, p1 string) error {
|
||||
if s.Internal.StorageAddLocal == nil {
|
||||
return ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageAddLocal(p0, p1)
|
||||
}
|
||||
|
||||
func (s *CurioStub) StorageAddLocal(p0 context.Context, p1 string) error {
|
||||
return ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *CurioStruct) StorageDetachLocal(p0 context.Context, p1 string) error {
|
||||
if s.Internal.StorageDetachLocal == nil {
|
||||
return ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageDetachLocal(p0, p1)
|
||||
}
|
||||
|
||||
func (s *CurioStub) StorageDetachLocal(p0 context.Context, p1 string) error {
|
||||
return ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *CurioStruct) StorageFindSector(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 abi.SectorSize, p4 bool) ([]storiface.SectorStorageInfo, error) {
|
||||
if s.Internal.StorageFindSector == nil {
|
||||
return *new([]storiface.SectorStorageInfo), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageFindSector(p0, p1, p2, p3, p4)
|
||||
}
|
||||
|
||||
func (s *CurioStub) StorageFindSector(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 abi.SectorSize, p4 bool) ([]storiface.SectorStorageInfo, error) {
|
||||
return *new([]storiface.SectorStorageInfo), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *CurioStruct) StorageInfo(p0 context.Context, p1 storiface.ID) (storiface.StorageInfo, error) {
|
||||
if s.Internal.StorageInfo == nil {
|
||||
return *new(storiface.StorageInfo), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageInfo(p0, p1)
|
||||
}
|
||||
|
||||
func (s *CurioStub) StorageInfo(p0 context.Context, p1 storiface.ID) (storiface.StorageInfo, error) {
|
||||
return *new(storiface.StorageInfo), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *CurioStruct) StorageList(p0 context.Context) (map[storiface.ID][]storiface.Decl, error) {
|
||||
if s.Internal.StorageList == nil {
|
||||
return *new(map[storiface.ID][]storiface.Decl), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageList(p0)
|
||||
}
|
||||
|
||||
func (s *CurioStub) StorageList(p0 context.Context) (map[storiface.ID][]storiface.Decl, error) {
|
||||
return *new(map[storiface.ID][]storiface.Decl), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *CurioStruct) StorageLocal(p0 context.Context) (map[storiface.ID]string, error) {
|
||||
if s.Internal.StorageLocal == nil {
|
||||
return *new(map[storiface.ID]string), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageLocal(p0)
|
||||
}
|
||||
|
||||
func (s *CurioStub) StorageLocal(p0 context.Context) (map[storiface.ID]string, error) {
|
||||
return *new(map[storiface.ID]string), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *CurioStruct) StorageStat(p0 context.Context, p1 storiface.ID) (fsutil.FsStat, error) {
|
||||
if s.Internal.StorageStat == nil {
|
||||
return *new(fsutil.FsStat), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageStat(p0, p1)
|
||||
}
|
||||
|
||||
func (s *CurioStub) StorageStat(p0 context.Context, p1 storiface.ID) (fsutil.FsStat, error) {
|
||||
return *new(fsutil.FsStat), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *CurioStruct) Version(p0 context.Context) (Version, error) {
|
||||
if s.Internal.Version == nil {
|
||||
return *new(Version), ErrNotSupported
|
||||
}
|
||||
return s.Internal.Version(p0)
|
||||
}
|
||||
|
||||
func (s *CurioStub) Version(p0 context.Context) (Version, error) {
|
||||
return *new(Version), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *EthSubscriberStruct) EthSubscription(p0 context.Context, p1 jsonrpc.RawParams) error {
|
||||
if s.Internal.EthSubscription == nil {
|
||||
return ErrNotSupported
|
||||
@ -2606,14 +2720,14 @@ func (s *FullNodeStub) GasEstimateMessageGas(p0 context.Context, p1 *types.Messa
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) GetActorEvents(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {
|
||||
if s.Internal.GetActorEvents == nil {
|
||||
func (s *FullNodeStruct) GetActorEventsRaw(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {
|
||||
if s.Internal.GetActorEventsRaw == nil {
|
||||
return *new([]*types.ActorEvent), ErrNotSupported
|
||||
}
|
||||
return s.Internal.GetActorEvents(p0, p1)
|
||||
return s.Internal.GetActorEventsRaw(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) GetActorEvents(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {
|
||||
func (s *FullNodeStub) GetActorEventsRaw(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {
|
||||
return *new([]*types.ActorEvent), ErrNotSupported
|
||||
}
|
||||
|
||||
@ -3992,14 +4106,14 @@ func (s *FullNodeStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *FullNodeStruct) SubscribeActorEvents(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) {
|
||||
if s.Internal.SubscribeActorEvents == nil {
|
||||
func (s *FullNodeStruct) SubscribeActorEventsRaw(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) {
|
||||
if s.Internal.SubscribeActorEventsRaw == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.SubscribeActorEvents(p0, p1)
|
||||
return s.Internal.SubscribeActorEventsRaw(p0, p1)
|
||||
}
|
||||
|
||||
func (s *FullNodeStub) SubscribeActorEvents(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) {
|
||||
func (s *FullNodeStub) SubscribeActorEventsRaw(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
@ -4278,6 +4392,17 @@ func (s *GatewayStub) ChainGetBlockMessages(p0 context.Context, p1 cid.Cid) (*Bl
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) ChainGetEvents(p0 context.Context, p1 cid.Cid) ([]types.Event, error) {
|
||||
if s.Internal.ChainGetEvents == nil {
|
||||
return *new([]types.Event), ErrNotSupported
|
||||
}
|
||||
return s.Internal.ChainGetEvents(p0, p1)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) ChainGetEvents(p0 context.Context, p1 cid.Cid) ([]types.Event, error) {
|
||||
return *new([]types.Event), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) ChainGetGenesis(p0 context.Context) (*types.TipSet, error) {
|
||||
if s.Internal.ChainGetGenesis == nil {
|
||||
return nil, ErrNotSupported
|
||||
@ -4850,14 +4975,14 @@ func (s *GatewayStub) GasEstimateMessageGas(p0 context.Context, p1 *types.Messag
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) GetActorEvents(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {
|
||||
if s.Internal.GetActorEvents == nil {
|
||||
func (s *GatewayStruct) GetActorEventsRaw(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {
|
||||
if s.Internal.GetActorEventsRaw == nil {
|
||||
return *new([]*types.ActorEvent), ErrNotSupported
|
||||
}
|
||||
return s.Internal.GetActorEvents(p0, p1)
|
||||
return s.Internal.GetActorEventsRaw(p0, p1)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) GetActorEvents(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {
|
||||
func (s *GatewayStub) GetActorEventsRaw(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {
|
||||
return *new([]*types.ActorEvent), ErrNotSupported
|
||||
}
|
||||
|
||||
@ -5125,6 +5250,17 @@ func (s *GatewayStub) StateMarketStorageDeal(p0 context.Context, p1 abi.DealID,
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) StateMinerDeadlines(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]Deadline, error) {
|
||||
if s.Internal.StateMinerDeadlines == nil {
|
||||
return *new([]Deadline), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StateMinerDeadlines(p0, p1, p2)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) StateMinerDeadlines(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]Deadline, error) {
|
||||
return *new([]Deadline), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) StateMinerInfo(p0 context.Context, p1 address.Address, p2 types.TipSetKey) (MinerInfo, error) {
|
||||
if s.Internal.StateMinerInfo == nil {
|
||||
return *new(MinerInfo), ErrNotSupported
|
||||
@ -5268,14 +5404,14 @@ func (s *GatewayStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p3
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *GatewayStruct) SubscribeActorEvents(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) {
|
||||
if s.Internal.SubscribeActorEvents == nil {
|
||||
func (s *GatewayStruct) SubscribeActorEventsRaw(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) {
|
||||
if s.Internal.SubscribeActorEventsRaw == nil {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
return s.Internal.SubscribeActorEvents(p0, p1)
|
||||
return s.Internal.SubscribeActorEventsRaw(p0, p1)
|
||||
}
|
||||
|
||||
func (s *GatewayStub) SubscribeActorEvents(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) {
|
||||
func (s *GatewayStub) SubscribeActorEventsRaw(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
@ -5312,116 +5448,6 @@ func (s *GatewayStub) Web3ClientVersion(p0 context.Context) (string, error) {
|
||||
return "", ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *LotusProviderStruct) AllocatePieceToSector(p0 context.Context, p1 address.Address, p2 PieceDealInfo, p3 int64, p4 url.URL, p5 http.Header) (SectorOffset, error) {
|
||||
if s.Internal.AllocatePieceToSector == nil {
|
||||
return *new(SectorOffset), ErrNotSupported
|
||||
}
|
||||
return s.Internal.AllocatePieceToSector(p0, p1, p2, p3, p4, p5)
|
||||
}
|
||||
|
||||
func (s *LotusProviderStub) AllocatePieceToSector(p0 context.Context, p1 address.Address, p2 PieceDealInfo, p3 int64, p4 url.URL, p5 http.Header) (SectorOffset, error) {
|
||||
return *new(SectorOffset), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *LotusProviderStruct) Shutdown(p0 context.Context) error {
|
||||
if s.Internal.Shutdown == nil {
|
||||
return ErrNotSupported
|
||||
}
|
||||
return s.Internal.Shutdown(p0)
|
||||
}
|
||||
|
||||
func (s *LotusProviderStub) Shutdown(p0 context.Context) error {
|
||||
return ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *LotusProviderStruct) StorageAddLocal(p0 context.Context, p1 string) error {
|
||||
if s.Internal.StorageAddLocal == nil {
|
||||
return ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageAddLocal(p0, p1)
|
||||
}
|
||||
|
||||
func (s *LotusProviderStub) StorageAddLocal(p0 context.Context, p1 string) error {
|
||||
return ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *LotusProviderStruct) StorageDetachLocal(p0 context.Context, p1 string) error {
|
||||
if s.Internal.StorageDetachLocal == nil {
|
||||
return ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageDetachLocal(p0, p1)
|
||||
}
|
||||
|
||||
func (s *LotusProviderStub) StorageDetachLocal(p0 context.Context, p1 string) error {
|
||||
return ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *LotusProviderStruct) StorageFindSector(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 abi.SectorSize, p4 bool) ([]storiface.SectorStorageInfo, error) {
|
||||
if s.Internal.StorageFindSector == nil {
|
||||
return *new([]storiface.SectorStorageInfo), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageFindSector(p0, p1, p2, p3, p4)
|
||||
}
|
||||
|
||||
func (s *LotusProviderStub) StorageFindSector(p0 context.Context, p1 abi.SectorID, p2 storiface.SectorFileType, p3 abi.SectorSize, p4 bool) ([]storiface.SectorStorageInfo, error) {
|
||||
return *new([]storiface.SectorStorageInfo), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *LotusProviderStruct) StorageInfo(p0 context.Context, p1 storiface.ID) (storiface.StorageInfo, error) {
|
||||
if s.Internal.StorageInfo == nil {
|
||||
return *new(storiface.StorageInfo), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageInfo(p0, p1)
|
||||
}
|
||||
|
||||
func (s *LotusProviderStub) StorageInfo(p0 context.Context, p1 storiface.ID) (storiface.StorageInfo, error) {
|
||||
return *new(storiface.StorageInfo), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *LotusProviderStruct) StorageList(p0 context.Context) (map[storiface.ID][]storiface.Decl, error) {
|
||||
if s.Internal.StorageList == nil {
|
||||
return *new(map[storiface.ID][]storiface.Decl), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageList(p0)
|
||||
}
|
||||
|
||||
func (s *LotusProviderStub) StorageList(p0 context.Context) (map[storiface.ID][]storiface.Decl, error) {
|
||||
return *new(map[storiface.ID][]storiface.Decl), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *LotusProviderStruct) StorageLocal(p0 context.Context) (map[storiface.ID]string, error) {
|
||||
if s.Internal.StorageLocal == nil {
|
||||
return *new(map[storiface.ID]string), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageLocal(p0)
|
||||
}
|
||||
|
||||
func (s *LotusProviderStub) StorageLocal(p0 context.Context) (map[storiface.ID]string, error) {
|
||||
return *new(map[storiface.ID]string), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *LotusProviderStruct) StorageStat(p0 context.Context, p1 storiface.ID) (fsutil.FsStat, error) {
|
||||
if s.Internal.StorageStat == nil {
|
||||
return *new(fsutil.FsStat), ErrNotSupported
|
||||
}
|
||||
return s.Internal.StorageStat(p0, p1)
|
||||
}
|
||||
|
||||
func (s *LotusProviderStub) StorageStat(p0 context.Context, p1 storiface.ID) (fsutil.FsStat, error) {
|
||||
return *new(fsutil.FsStat), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *LotusProviderStruct) Version(p0 context.Context) (Version, error) {
|
||||
if s.Internal.Version == nil {
|
||||
return *new(Version), ErrNotSupported
|
||||
}
|
||||
return s.Internal.Version(p0)
|
||||
}
|
||||
|
||||
func (s *LotusProviderStub) Version(p0 context.Context) (Version, error) {
|
||||
return *new(Version), ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *NetStruct) ID(p0 context.Context) (peer.ID, error) {
|
||||
if s.Internal.ID == nil {
|
||||
return *new(peer.ID), ErrNotSupported
|
||||
@ -7647,10 +7673,10 @@ func (s *WorkerStub) WaitQuiet(p0 context.Context) error {
|
||||
var _ ChainIO = new(ChainIOStruct)
|
||||
var _ Common = new(CommonStruct)
|
||||
var _ CommonNet = new(CommonNetStruct)
|
||||
var _ Curio = new(CurioStruct)
|
||||
var _ EthSubscriber = new(EthSubscriberStruct)
|
||||
var _ FullNode = new(FullNodeStruct)
|
||||
var _ Gateway = new(GatewayStruct)
|
||||
var _ LotusProvider = new(LotusProviderStruct)
|
||||
var _ Net = new(NetStruct)
|
||||
var _ Signable = new(SignableStruct)
|
||||
var _ StorageMiner = new(StorageMinerStruct)
|
||||
|
@ -13,4 +13,4 @@ func PermissionedFullAPI(a FullNode) FullNode {
|
||||
return api.PermissionedFullAPI(a)
|
||||
}
|
||||
|
||||
type LotusProviderStruct = api.LotusProviderStruct
|
||||
type CurioStruct = api.CurioStruct
|
||||
|
@ -60,7 +60,7 @@ var (
|
||||
MinerAPIVersion0 = newVer(1, 5, 0)
|
||||
WorkerAPIVersion0 = newVer(1, 7, 0)
|
||||
|
||||
ProviderAPIVersion0 = newVer(1, 0, 0)
|
||||
CurioAPIVersion0 = newVer(1, 0, 0)
|
||||
)
|
||||
|
||||
//nolint:varcheck,deadcode
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -242,7 +242,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4259"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4373"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -473,7 +473,106 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4270"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4384"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Filecoin.ChainGetEvents",
|
||||
"description": "```go\nfunc (s *GatewayStruct) ChainGetEvents(p0 context.Context, p1 cid.Cid) ([]types.Event, error) {\n\tif s.Internal.ChainGetEvents == nil {\n\t\treturn *new([]types.Event), ErrNotSupported\n\t}\n\treturn s.Internal.ChainGetEvents(p0, p1)\n}\n```",
|
||||
"summary": "There are not yet any comments for this method.",
|
||||
"paramStructure": "by-position",
|
||||
"params": [
|
||||
{
|
||||
"name": "p1",
|
||||
"description": "cid.Cid",
|
||||
"summary": "",
|
||||
"schema": {
|
||||
"title": "Content Identifier",
|
||||
"description": "Cid represents a self-describing content addressed identifier. It is formed by a Version, a Codec (which indicates a multicodec-packed content type) and a Multihash.",
|
||||
"examples": [
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
"string"
|
||||
]
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "[]types.Event",
|
||||
"description": "[]types.Event",
|
||||
"summary": "",
|
||||
"schema": {
|
||||
"examples": [
|
||||
[
|
||||
{
|
||||
"Emitter": 1000,
|
||||
"Entries": [
|
||||
{
|
||||
"Flags": 7,
|
||||
"Key": "string value",
|
||||
"Codec": 42,
|
||||
"Value": "Ynl0ZSBhcnJheQ=="
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"Emitter": {
|
||||
"title": "number",
|
||||
"type": "number"
|
||||
},
|
||||
"Entries": {
|
||||
"items": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"Codec": {
|
||||
"title": "number",
|
||||
"type": "number"
|
||||
},
|
||||
"Flags": {
|
||||
"title": "number",
|
||||
"type": "number"
|
||||
},
|
||||
"Key": {
|
||||
"type": "string"
|
||||
},
|
||||
"Value": {
|
||||
"media": {
|
||||
"binaryEncoding": "base64"
|
||||
},
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": [
|
||||
"object"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
"array"
|
||||
]
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4395"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -505,7 +604,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4281"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4406"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -611,7 +710,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4292"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4417"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -704,7 +803,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4303"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4428"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -788,7 +887,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4314"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4439"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -888,7 +987,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4325"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4450"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -944,7 +1043,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4336"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4461"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1017,7 +1116,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4347"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4472"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1090,7 +1189,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4358"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4483"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1137,7 +1236,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4369"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4494"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1169,7 +1268,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4380"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4505"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1206,7 +1305,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4402"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4527"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1253,7 +1352,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4413"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4538"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1293,7 +1392,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4424"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4549"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1340,7 +1439,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4435"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4560"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1369,7 +1468,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4446"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4571"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1506,7 +1605,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4457"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4582"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1535,7 +1634,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4468"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4593"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1589,7 +1688,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4479"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4604"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1680,7 +1779,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4490"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4615"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1708,7 +1807,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4501"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4626"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1798,7 +1897,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4512"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4637"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2054,7 +2153,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4523"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4648"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2299,7 +2398,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4534"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4659"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2355,7 +2454,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4545"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4670"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2402,7 +2501,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4556"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4681"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2500,7 +2599,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4567"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4692"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2566,7 +2665,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4578"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4703"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2632,7 +2731,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4589"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4714"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2741,7 +2840,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4600"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4725"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2799,7 +2898,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4611"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4736"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2921,7 +3020,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4622"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4747"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3108,7 +3207,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4633"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4758"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3312,7 +3411,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4644"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4769"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3403,7 +3502,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4655"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4780"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3461,7 +3560,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4666"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4791"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3719,7 +3818,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4677"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4802"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3994,7 +4093,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4688"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4813"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4022,7 +4121,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4699"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4824"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4060,7 +4159,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4710"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4835"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4168,7 +4267,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4721"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4846"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4206,7 +4305,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4732"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4857"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4235,7 +4334,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4743"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4868"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4298,7 +4397,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4754"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4879"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4361,7 +4460,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4765"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4890"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4406,7 +4505,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4776"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4901"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4528,7 +4627,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4787"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4912"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4683,7 +4782,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4798"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4923"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4737,7 +4836,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4809"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4934"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4791,7 +4890,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4820"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4945"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4893,7 +4992,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4831"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4956"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5116,12 +5215,12 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4842"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4967"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Filecoin.GetActorEvents",
|
||||
"description": "```go\nfunc (s *GatewayStruct) GetActorEvents(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {\n\tif s.Internal.GetActorEvents == nil {\n\t\treturn *new([]*types.ActorEvent), ErrNotSupported\n\t}\n\treturn s.Internal.GetActorEvents(p0, p1)\n}\n```",
|
||||
"name": "Filecoin.GetActorEventsRaw",
|
||||
"description": "```go\nfunc (s *GatewayStruct) GetActorEventsRaw(p0 context.Context, p1 *types.ActorEventFilter) ([]*types.ActorEvent, error) {\n\tif s.Internal.GetActorEventsRaw == nil {\n\t\treturn *new([]*types.ActorEvent), ErrNotSupported\n\t}\n\treturn s.Internal.GetActorEventsRaw(p0, p1)\n}\n```",
|
||||
"summary": "There are not yet any comments for this method.",
|
||||
"paramStructure": "by-position",
|
||||
"params": [
|
||||
@ -5299,7 +5398,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4853"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4978"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5493,7 +5592,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4864"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4989"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5539,7 +5638,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4875"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5000"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5689,7 +5788,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4886"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5011"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5826,7 +5925,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4897"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5022"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5894,7 +5993,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4908"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5033"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6011,7 +6110,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4919"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5044"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6102,7 +6201,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4930"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5055"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6188,7 +6287,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4941"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5066"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6215,7 +6314,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4952"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5077"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6242,7 +6341,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4963"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5088"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6310,7 +6409,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4974"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5099"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6816,7 +6915,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4985"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5110"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6913,7 +7012,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L4996"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5121"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7013,7 +7112,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5007"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5132"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7113,7 +7212,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5018"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5143"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7238,7 +7337,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5029"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5154"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7347,7 +7446,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5040"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5165"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7450,7 +7549,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5051"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5176"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7580,7 +7679,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5062"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5187"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7687,7 +7786,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5073"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5198"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7748,7 +7847,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5084"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5209"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7816,7 +7915,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5095"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5220"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7897,7 +7996,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5106"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5231"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -8056,7 +8155,100 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5117"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5242"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Filecoin.StateMinerDeadlines",
|
||||
"description": "```go\nfunc (s *GatewayStruct) StateMinerDeadlines(p0 context.Context, p1 address.Address, p2 types.TipSetKey) ([]Deadline, error) {\n\tif s.Internal.StateMinerDeadlines == nil {\n\t\treturn *new([]Deadline), ErrNotSupported\n\t}\n\treturn s.Internal.StateMinerDeadlines(p0, p1, p2)\n}\n```",
|
||||
"summary": "There are not yet any comments for this method.",
|
||||
"paramStructure": "by-position",
|
||||
"params": [
|
||||
{
|
||||
"name": "p1",
|
||||
"description": "address.Address",
|
||||
"summary": "",
|
||||
"schema": {
|
||||
"examples": [
|
||||
"f01234"
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"type": [
|
||||
"object"
|
||||
]
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
{
|
||||
"name": "p2",
|
||||
"description": "types.TipSetKey",
|
||||
"summary": "",
|
||||
"schema": {
|
||||
"examples": [
|
||||
[
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
{
|
||||
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
|
||||
}
|
||||
]
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"type": [
|
||||
"object"
|
||||
]
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
}
|
||||
],
|
||||
"result": {
|
||||
"name": "[]Deadline",
|
||||
"description": "[]Deadline",
|
||||
"summary": "",
|
||||
"schema": {
|
||||
"examples": [
|
||||
[
|
||||
{
|
||||
"PostSubmissions": [
|
||||
5,
|
||||
1
|
||||
],
|
||||
"DisputableProofCount": 42
|
||||
}
|
||||
]
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"DisputableProofCount": {
|
||||
"title": "number",
|
||||
"type": "number"
|
||||
},
|
||||
"PostSubmissions": {
|
||||
"additionalProperties": false,
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": [
|
||||
"object"
|
||||
]
|
||||
}
|
||||
],
|
||||
"type": [
|
||||
"array"
|
||||
]
|
||||
},
|
||||
"required": true,
|
||||
"deprecated": false
|
||||
},
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5253"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -8257,7 +8449,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5128"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5264"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -8368,7 +8560,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5139"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5275"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -8499,7 +8691,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5150"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5286"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -8585,7 +8777,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5161"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5297"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -8612,7 +8804,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5172"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5308"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -8665,7 +8857,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5183"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5319"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -8753,7 +8945,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5194"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5330"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -9204,7 +9396,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5205"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5341"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -9371,7 +9563,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5216"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5352"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -9544,7 +9736,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5227"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5363"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -9612,7 +9804,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5238"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5374"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -9680,7 +9872,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5249"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5385"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -9841,7 +10033,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5260"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5396"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -9886,7 +10078,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5282"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5418"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -9931,7 +10123,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5293"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5429"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -9958,7 +10150,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5304"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L5440"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -161,7 +161,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7240"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7266"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -252,7 +252,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7251"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7277"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -420,7 +420,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7262"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7288"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -447,7 +447,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7273"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7299"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -597,7 +597,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7284"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7310"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -700,7 +700,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7295"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7321"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -803,7 +803,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7306"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7332"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -925,7 +925,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7317"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7343"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1135,7 +1135,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7328"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7354"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1306,7 +1306,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7339"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7365"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3350,7 +3350,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7350"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7376"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3470,7 +3470,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7361"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7387"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3531,7 +3531,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7372"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7398"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3569,7 +3569,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7383"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7409"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3729,7 +3729,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7394"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7420"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3913,7 +3913,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7405"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7431"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4054,7 +4054,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7416"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7442"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4107,7 +4107,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7427"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7453"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4250,7 +4250,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7438"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7464"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4474,7 +4474,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7449"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7475"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4601,7 +4601,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7460"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7486"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4768,7 +4768,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7471"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7497"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4895,7 +4895,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7482"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7508"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4933,7 +4933,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7493"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7519"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4972,7 +4972,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7504"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7530"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4995,7 +4995,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7515"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7541"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5034,7 +5034,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7526"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7552"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5057,7 +5057,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7537"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7563"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5096,7 +5096,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7548"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7574"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5130,7 +5130,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7559"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7585"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5184,7 +5184,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7570"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7596"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5223,7 +5223,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7581"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7607"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5262,7 +5262,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7592"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7618"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5297,7 +5297,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7603"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7629"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5477,7 +5477,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7614"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7640"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5506,7 +5506,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7625"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7651"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5529,7 +5529,7 @@
|
||||
"deprecated": false,
|
||||
"externalDocs": {
|
||||
"description": "Github remote link",
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7636"
|
||||
"url": "https://github.com/filecoin-project/lotus/blob/master/api/proxy_gen.go#L7662"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -45,8 +45,8 @@ var ddls = []string{
|
||||
reverted INTEGER NOT NULL
|
||||
)`,
|
||||
|
||||
`CREATE INDEX IF NOT EXISTS height_tipset_key ON event (height,tipset_key)`,
|
||||
`CREATE INDEX IF NOT EXISTS event_emitter_addr ON event (emitter_addr)`,
|
||||
createIndexEventHeightTipsetKey,
|
||||
createIndexEventEmitterAddr,
|
||||
|
||||
`CREATE TABLE IF NOT EXISTS event_entry (
|
||||
event_id INTEGER,
|
||||
@ -57,7 +57,7 @@ var ddls = []string{
|
||||
value BLOB NOT NULL
|
||||
)`,
|
||||
|
||||
`CREATE INDEX IF NOT EXISTS event_entry_key_index ON event_entry (key)`,
|
||||
createIndexEventEntryKey,
|
||||
|
||||
// metadata containing version of schema
|
||||
`CREATE TABLE IF NOT EXISTS _meta (
|
||||
@ -81,6 +81,10 @@ const (
|
||||
insertEntry = `INSERT OR IGNORE INTO event_entry(event_id, indexed, flags, key, codec, value) VALUES(?, ?, ?, ?, ?, ?)`
|
||||
revertEventsInTipset = `UPDATE event SET reverted=true WHERE height=? AND tipset_key=?`
|
||||
restoreEvent = `UPDATE event SET reverted=false WHERE height=? AND tipset_key=? AND tipset_key_cid=? AND emitter_addr=? AND event_index=? AND message_cid=? AND message_index=?`
|
||||
|
||||
createIndexEventHeightTipsetKey = `CREATE INDEX IF NOT EXISTS height_tipset_key ON event (height,tipset_key)`
|
||||
createIndexEventEmitterAddr = `CREATE INDEX IF NOT EXISTS event_emitter_addr ON event (emitter_addr)`
|
||||
createIndexEventEntryKey = `CREATE INDEX IF NOT EXISTS event_entry_key_index ON event_entry (key)`
|
||||
)
|
||||
|
||||
type EventIndex struct {
|
||||
@ -125,43 +129,43 @@ func (ei *EventIndex) initStatements() (err error) {
|
||||
func (ei *EventIndex) migrateToVersion2(ctx context.Context, chainStore *store.ChainStore) error {
|
||||
now := time.Now()
|
||||
|
||||
tx, err := ei.db.Begin()
|
||||
tx, err := ei.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("begin transaction: %w", err)
|
||||
}
|
||||
// rollback the transaction (a no-op if the transaction was already committed)
|
||||
defer tx.Rollback() //nolint:errcheck
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
// create some temporary indices to help speed up the migration
|
||||
_, err = tx.Exec("CREATE INDEX IF NOT EXISTS tmp_height_tipset_key_cid ON event (height,tipset_key_cid)")
|
||||
_, err = tx.ExecContext(ctx, "CREATE INDEX IF NOT EXISTS tmp_height_tipset_key_cid ON event (height,tipset_key_cid)")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("create index tmp_height_tipset_key_cid: %w", err)
|
||||
}
|
||||
_, err = tx.Exec("CREATE INDEX IF NOT EXISTS tmp_tipset_key_cid ON event (tipset_key_cid)")
|
||||
_, err = tx.ExecContext(ctx, "CREATE INDEX IF NOT EXISTS tmp_tipset_key_cid ON event (tipset_key_cid)")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("create index tmp_tipset_key_cid: %w", err)
|
||||
}
|
||||
|
||||
stmtDeleteOffChainEvent, err := tx.Prepare("DELETE FROM event WHERE tipset_key_cid!=? and height=?")
|
||||
stmtDeleteOffChainEvent, err := tx.PrepareContext(ctx, "DELETE FROM event WHERE tipset_key_cid!=? and height=?")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("prepare stmtDeleteOffChainEvent: %w", err)
|
||||
}
|
||||
|
||||
stmtSelectEvent, err := tx.Prepare("SELECT id FROM event WHERE tipset_key_cid=? ORDER BY message_index ASC, event_index ASC, id DESC LIMIT 1")
|
||||
stmtSelectEvent, err := tx.PrepareContext(ctx, "SELECT id FROM event WHERE tipset_key_cid=? ORDER BY message_index ASC, event_index ASC, id DESC LIMIT 1")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("prepare stmtSelectEvent: %w", err)
|
||||
}
|
||||
|
||||
stmtDeleteEvent, err := tx.Prepare("DELETE FROM event WHERE tipset_key_cid=? AND id<?")
|
||||
stmtDeleteEvent, err := tx.PrepareContext(ctx, "DELETE FROM event WHERE tipset_key_cid=? AND id<?")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("prepare stmtDeleteEvent: %w", err)
|
||||
}
|
||||
|
||||
// get the lowest height tipset
|
||||
var minHeight sql.NullInt64
|
||||
err = ei.db.QueryRow("SELECT MIN(height) FROM event").Scan(&minHeight)
|
||||
err = ei.db.QueryRowContext(ctx, "SELECT MIN(height) FROM event").Scan(&minHeight)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -198,7 +202,7 @@ func (ei *EventIndex) migrateToVersion2(ctx context.Context, chainStore *store.C
|
||||
var eventId sql.NullInt64
|
||||
err = stmtSelectEvent.QueryRow(tsKeyCid.Bytes()).Scan(&eventId)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
continue
|
||||
}
|
||||
return xerrors.Errorf("select event: %w", err)
|
||||
@ -224,7 +228,7 @@ func (ei *EventIndex) migrateToVersion2(ctx context.Context, chainStore *store.C
|
||||
|
||||
// delete all entries that have an event_id that doesn't exist (since we don't have a foreign
|
||||
// key constraint that gives us cascading deletes)
|
||||
res, err := tx.Exec("DELETE FROM event_entry WHERE event_id NOT IN (SELECT id FROM event)")
|
||||
res, err := tx.ExecContext(ctx, "DELETE FROM event_entry WHERE event_id NOT IN (SELECT id FROM event)")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("delete event_entry: %w", err)
|
||||
}
|
||||
@ -236,15 +240,27 @@ func (ei *EventIndex) migrateToVersion2(ctx context.Context, chainStore *store.C
|
||||
log.Infof("cleaned up %d entries that had deleted events\n", nrRowsAffected)
|
||||
|
||||
// drop the temporary indices after the migration
|
||||
_, err = tx.Exec("DROP INDEX IF EXISTS tmp_tipset_key_cid")
|
||||
_, err = tx.ExecContext(ctx, "DROP INDEX IF EXISTS tmp_tipset_key_cid")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("create index tmp_tipset_key_cid: %w", err)
|
||||
return xerrors.Errorf("drop index tmp_tipset_key_cid: %w", err)
|
||||
}
|
||||
_, err = tx.Exec("DROP INDEX IF EXISTS tmp_height_tipset_key_cid")
|
||||
_, err = tx.ExecContext(ctx, "DROP INDEX IF EXISTS tmp_height_tipset_key_cid")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("drop index tmp_height_tipset_key_cid: %w", err)
|
||||
}
|
||||
|
||||
// create the final index on event.height and event.tipset_key
|
||||
_, err = tx.ExecContext(ctx, createIndexEventHeightTipsetKey)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("create index height_tipset_key: %w", err)
|
||||
}
|
||||
|
||||
// increment the schema version to 2 in _meta table.
|
||||
_, err = tx.ExecContext(ctx, "INSERT OR IGNORE INTO _meta (version) VALUES (2)")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("increment _meta version: %w", err)
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("commit transaction: %w", err)
|
||||
@ -254,11 +270,11 @@ func (ei *EventIndex) migrateToVersion2(ctx context.Context, chainStore *store.C
|
||||
// simple DB administration to free up space (VACUUM followed by truncating the WAL file)
|
||||
// as this would be a good time to do it when no other writes are happening
|
||||
log.Infof("Performing DB vacuum and wal checkpointing to free up space after the migration")
|
||||
_, err = ei.db.Exec("VACUUM")
|
||||
_, err = ei.db.ExecContext(ctx, "VACUUM")
|
||||
if err != nil {
|
||||
log.Warnf("error vacuuming database: %s", err)
|
||||
}
|
||||
_, err = ei.db.Exec("PRAGMA wal_checkpoint(TRUNCATE)")
|
||||
_, err = ei.db.ExecContext(ctx, "PRAGMA wal_checkpoint(TRUNCATE)")
|
||||
if err != nil {
|
||||
log.Warnf("error checkpointing wal: %s", err)
|
||||
}
|
||||
@ -268,6 +284,43 @@ func (ei *EventIndex) migrateToVersion2(ctx context.Context, chainStore *store.C
|
||||
return nil
|
||||
}
|
||||
|
||||
// migrateToVersion3 migrates the schema from version 2 to version 3 by creating two indices:
|
||||
// 1) an index on the event.emitter_addr column, and 2) an index on the event_entry.key column.
|
||||
func (ei *EventIndex) migrateToVersion3(ctx context.Context) error {
|
||||
now := time.Now()
|
||||
|
||||
tx, err := ei.db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("begin transaction: %w", err)
|
||||
}
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
// create index on event.emitter_addr.
|
||||
_, err = tx.ExecContext(ctx, createIndexEventEmitterAddr)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("create index event_emitter_addr: %w", err)
|
||||
}
|
||||
|
||||
// create index on event_entry.key index.
|
||||
_, err = tx.ExecContext(ctx, createIndexEventEntryKey)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("create index event_entry_key_index: %w", err)
|
||||
}
|
||||
|
||||
// increment the schema version to 3 in _meta table.
|
||||
_, err = tx.ExecContext(ctx, "INSERT OR IGNORE INTO _meta (version) VALUES (3)")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("increment _meta version: %w", err)
|
||||
}
|
||||
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("commit transaction: %w", err)
|
||||
}
|
||||
log.Infof("Successfully migrated events to version 3 in %s", time.Since(now))
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewEventIndex(ctx context.Context, path string, chainStore *store.ChainStore) (*EventIndex, error) {
|
||||
db, err := sql.Open("sqlite3", path+"?mode=rwc")
|
||||
if err != nil {
|
||||
@ -283,8 +336,8 @@ func NewEventIndex(ctx context.Context, path string, chainStore *store.ChainStor
|
||||
|
||||
eventIndex := EventIndex{db: db}
|
||||
|
||||
q, err := db.Query("SELECT name FROM sqlite_master WHERE type='table' AND name='_meta';")
|
||||
if err == sql.ErrNoRows || !q.Next() {
|
||||
q, err := db.QueryContext(ctx, "SELECT name FROM sqlite_master WHERE type='table' AND name='_meta';")
|
||||
if errors.Is(err, sql.ErrNoRows) || !q.Next() {
|
||||
// empty database, create the schema
|
||||
for _, ddl := range ddls {
|
||||
if _, err := db.Exec(ddl); err != nil {
|
||||
@ -306,38 +359,21 @@ func NewEventIndex(ctx context.Context, path string, chainStore *store.ChainStor
|
||||
|
||||
if version == 1 {
|
||||
log.Infof("upgrading event index from version 1 to version 2")
|
||||
|
||||
err = eventIndex.migrateToVersion2(ctx, chainStore)
|
||||
if err != nil {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("could not migrate sql data to version 2: %w", err)
|
||||
}
|
||||
|
||||
// to upgrade to version version 2 we only need to create an index on the event table
|
||||
// which means we can just recreate the schema (it will not have any effect on existing data)
|
||||
for _, ddl := range ddls {
|
||||
if _, err := db.Exec(ddl); err != nil {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("could not upgrade index to version 2, exec ddl %q: %w", ddl, err)
|
||||
}
|
||||
}
|
||||
|
||||
version = 2
|
||||
}
|
||||
|
||||
if version == 2 {
|
||||
log.Infof("upgrading event index from version 2 to version 3")
|
||||
|
||||
// to upgrade to version 3 we only need to create an index on the event_entry.key column
|
||||
// and on the event.emitter_addr column
|
||||
// which means we can just reapply the schema (it will not have any effect on existing data)
|
||||
for _, ddl := range ddls {
|
||||
if _, err := db.Exec(ddl); err != nil {
|
||||
err = eventIndex.migrateToVersion3(ctx)
|
||||
if err != nil {
|
||||
_ = db.Close()
|
||||
return nil, xerrors.Errorf("could not upgrade index to version 3, exec ddl %q: %w", ddl, err)
|
||||
return nil, xerrors.Errorf("could not migrate sql data to version 2: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
version = 3
|
||||
}
|
||||
|
||||
@ -369,7 +405,7 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever
|
||||
return xerrors.Errorf("begin transaction: %w", err)
|
||||
}
|
||||
// rollback the transaction (a no-op if the transaction was already committed)
|
||||
defer tx.Rollback() //nolint:errcheck
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
// lets handle the revert case first, since its simpler and we can simply mark all events events in this tipset as reverted and return
|
||||
if revert {
|
||||
@ -500,11 +536,12 @@ func (ei *EventIndex) CollectEvents(ctx context.Context, te *TipSetEvents, rever
|
||||
return nil
|
||||
}
|
||||
|
||||
// PrefillFilter fills a filter's collection of events from the historic index
|
||||
// prefillFilter fills a filter's collection of events from the historic index
|
||||
func (ei *EventIndex) prefillFilter(ctx context.Context, f *eventFilter, excludeReverted bool) error {
|
||||
clauses := []string{}
|
||||
values := []any{}
|
||||
joins := []string{}
|
||||
var (
|
||||
clauses, joins []string
|
||||
values []any
|
||||
)
|
||||
|
||||
if f.tipsetCid != cid.Undef {
|
||||
clauses = append(clauses, "event.tipset_key_cid=?")
|
||||
@ -526,7 +563,7 @@ func (ei *EventIndex) prefillFilter(ctx context.Context, f *eventFilter, exclude
|
||||
}
|
||||
|
||||
if len(f.addresses) > 0 {
|
||||
subclauses := []string{}
|
||||
subclauses := make([]string, 0, len(f.addresses))
|
||||
for _, addr := range f.addresses {
|
||||
subclauses = append(subclauses, "emitter_addr=?")
|
||||
values = append(values, addr.Bytes())
|
||||
@ -543,7 +580,7 @@ func (ei *EventIndex) prefillFilter(ctx context.Context, f *eventFilter, exclude
|
||||
joins = append(joins, fmt.Sprintf("event_entry %s on event.id=%[1]s.event_id", joinAlias))
|
||||
clauses = append(clauses, fmt.Sprintf("%s.indexed=1 AND %[1]s.key=?", joinAlias))
|
||||
values = append(values, key)
|
||||
subclauses := []string{}
|
||||
subclauses := make([]string, 0, len(vals))
|
||||
for _, val := range vals {
|
||||
subclauses = append(subclauses, fmt.Sprintf("(%s.value=? AND %[1]s.codec=?)", joinAlias))
|
||||
values = append(values, val.Value, val.Codec)
|
||||
|
@ -369,7 +369,7 @@ func (sp *StatePredicates) OnMinerPreCommitChange() DiffMinerActorStateFunc {
|
||||
// DiffPaymentChannelStateFunc is function that compares two states for the payment channel
|
||||
type DiffPaymentChannelStateFunc func(ctx context.Context, oldState paych.State, newState paych.State) (changed bool, user UserData, err error)
|
||||
|
||||
// OnPaymentChannelActorChanged calls diffPaymentChannelState when the state changes for the the payment channel actor
|
||||
// OnPaymentChannelActorChanged calls diffPaymentChannelState when the state changes for the payment channel actor
|
||||
func (sp *StatePredicates) OnPaymentChannelActorChanged(paychAddr address.Address, diffPaymentChannelState DiffPaymentChannelStateFunc) DiffTipSetKeyFunc {
|
||||
return sp.OnActorStateChanged(paychAddr, func(ctx context.Context, oldActorState, newActorState *types.Actor) (changed bool, user UserData, err error) {
|
||||
oldState, err := paych.Load(adt.WrapStore(ctx, sp.cst), oldActorState)
|
||||
|
@ -1191,7 +1191,7 @@ func TestOptimalMessageSelection2(t *testing.T) {
|
||||
func TestOptimalMessageSelection3(t *testing.T) {
|
||||
//stm: @TOKEN_WALLET_NEW_001, @CHAIN_MEMPOOL_SELECT_001
|
||||
|
||||
// this test uses 10 actors sending a block of messages to each other, with the the first
|
||||
// this test uses 10 actors sending a block of messages to each other, with the first
|
||||
// actors paying higher gas premium than the subsequent actors.
|
||||
// We select with a low ticket quality; the chain dependent merging algorithm should pick
|
||||
// messages from the median actor from the start
|
||||
|
@ -182,8 +182,16 @@ func (sm *StateManager) HandleStateForks(ctx context.Context, root cid.Cid, heig
|
||||
if err == nil {
|
||||
if ok {
|
||||
log.Infow("CACHED migration", "height", height, "from", root, "to", migCid)
|
||||
foundMigratedRoot, err := sm.ChainStore().StateBlockstore().Has(ctx, migCid)
|
||||
if err != nil {
|
||||
log.Errorw("failed to check whether previous migration result is present", "err", err)
|
||||
} else if !foundMigratedRoot {
|
||||
log.Errorw("cached migration result not found in blockstore, running migration again")
|
||||
u.migrationResultCache.Delete(ctx, root)
|
||||
} else {
|
||||
return migCid, nil
|
||||
}
|
||||
}
|
||||
} else if !errors.Is(err, datastore.ErrNotFound) {
|
||||
log.Errorw("failed to lookup previous migration result", "err", err)
|
||||
} else {
|
||||
|
@ -113,6 +113,10 @@ func (m *migrationResultCache) Store(ctx context.Context, root cid.Cid, resultCi
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *migrationResultCache) Delete(ctx context.Context, root cid.Cid) {
|
||||
_ = m.ds.Delete(ctx, m.keyForMigration(root))
|
||||
}
|
||||
|
||||
type Executor interface {
|
||||
NewActorRegistry() *vm.ActorRegistry
|
||||
ExecuteTipSet(ctx context.Context, sm *StateManager, ts *types.TipSet, em ExecMonitor, vmTracing bool) (stateroot cid.Cid, rectsroot cid.Cid, err error)
|
||||
|
@ -357,7 +357,7 @@ func (sm *syncManager) selectInitialSyncTarget() (*types.TipSet, error) {
|
||||
return buckets.Heaviest(), nil
|
||||
}
|
||||
|
||||
// adds a tipset to the potential sync targets; returns true if there is a a tipset to work on.
|
||||
// adds a tipset to the potential sync targets; returns true if there is a tipset to work on.
|
||||
// this could be either a restart, eg because there is no currently scheduled sync work or a worker
|
||||
// failed or a potential fork.
|
||||
func (sm *syncManager) addSyncTarget(ts *types.TipSet) (*types.TipSet, bool, error) {
|
||||
|
435
cli/filplus.go
435
cli/filplus.go
@ -4,23 +4,30 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/manifoldco/promptui"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
verifregtypes13 "github.com/filecoin-project/go-state-types/builtin/v13/verifreg"
|
||||
verifregtypes8 "github.com/filecoin-project/go-state-types/builtin/v8/verifreg"
|
||||
datacap2 "github.com/filecoin-project/go-state-types/builtin/v9/datacap"
|
||||
verifregtypes9 "github.com/filecoin-project/go-state-types/builtin/v9/verifreg"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/v0api"
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
@ -47,6 +54,7 @@ var filplusCmd = &cli.Command{
|
||||
filplusListClaimsCmd,
|
||||
filplusRemoveExpiredAllocationsCmd,
|
||||
filplusRemoveExpiredClaimsCmd,
|
||||
filplusExtendClaimCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@ -923,3 +931,430 @@ var filplusSignRemoveDataCapProposal = &cli.Command{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var filplusExtendClaimCmd = &cli.Command{
|
||||
Name: "extend-claim",
|
||||
Usage: "extend claim expiration (TermMax)",
|
||||
Flags: []cli.Flag{
|
||||
&cli.Int64Flag{
|
||||
Name: "term-max",
|
||||
Usage: "The maximum period for which a provider can earn quality-adjusted power for the piece (epochs). Default is 5 years.",
|
||||
Aliases: []string{"tmax"},
|
||||
Value: verifregtypes13.MaximumVerifiedAllocationTerm,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "client",
|
||||
Usage: "the client address that will used to send the message",
|
||||
Required: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "all",
|
||||
Usage: "automatically extend TermMax of all claims for specified miner[s] to --term-max (default: 5 years from claim start epoch)",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "miner",
|
||||
Usage: "storage provider address[es]",
|
||||
Aliases: []string{"m", "provider", "p"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "assume-yes",
|
||||
Usage: "automatic yes to prompts; assume 'yes' as answer to all prompts and run non-interactively",
|
||||
Aliases: []string{"y", "yes"},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "confidence",
|
||||
Usage: "number of block confirmations to wait for",
|
||||
Value: int(build.MessageConfidence),
|
||||
},
|
||||
},
|
||||
ArgsUsage: "<claim1> <claim2> ... or <miner1=claim1> <miner2=claims2> ...",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
|
||||
miners := cctx.StringSlice("miner")
|
||||
all := cctx.Bool("all")
|
||||
client := cctx.String("client")
|
||||
tmax := cctx.Int64("term-max")
|
||||
|
||||
// No miner IDs and no arguments
|
||||
if len(miners) == 0 && cctx.Args().Len() == 0 {
|
||||
return xerrors.Errorf("must specify at least one miner ID or argument[s]")
|
||||
}
|
||||
|
||||
// Single Miner with no claimID and no --all flag
|
||||
if len(miners) == 1 && cctx.Args().Len() == 0 && !all {
|
||||
return xerrors.Errorf("must specify either --all flag or claim IDs to extend in argument")
|
||||
}
|
||||
|
||||
// Multiple Miner with claimIDs
|
||||
if len(miners) > 1 && cctx.Args().Len() > 0 {
|
||||
return xerrors.Errorf("either specify multiple miner IDs or multiple arguments")
|
||||
}
|
||||
|
||||
// Multiple Miner with no claimID and no --all flag
|
||||
if len(miners) > 1 && cctx.Args().Len() == 0 && !all {
|
||||
return xerrors.Errorf("must specify --all flag with multiple miner IDs")
|
||||
}
|
||||
|
||||
// Tmax can't be more than policy max
|
||||
if tmax > verifregtypes13.MaximumVerifiedAllocationTerm {
|
||||
return xerrors.Errorf("specified term-max %d is larger than %d maximum allowed by verified regirty actor policy", tmax, verifregtypes13.MaximumVerifiedAllocationTerm)
|
||||
}
|
||||
|
||||
api, closer, err := GetFullNodeAPIV1(cctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to get full node api: %s", err)
|
||||
}
|
||||
defer closer()
|
||||
ctx := ReqContext(cctx)
|
||||
|
||||
clientAddr, err := address.NewFromString(client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
claimMap := make(map[verifregtypes13.ClaimId]ProvInfo)
|
||||
|
||||
// If no miners and arguments are present
|
||||
if len(miners) == 0 && cctx.Args().Len() > 0 {
|
||||
for _, arg := range cctx.Args().Slice() {
|
||||
detail := strings.Split(arg, "=")
|
||||
if len(detail) > 2 {
|
||||
return xerrors.Errorf("incorrect argument format: %s", detail)
|
||||
}
|
||||
|
||||
n, err := strconv.ParseInt(detail[1], 10, 64)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to parse the claim ID for %s for argument %s: %s", detail[0], detail, err)
|
||||
}
|
||||
|
||||
maddr, err := address.NewFromString(detail[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify that minerID exists
|
||||
_, err = api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mid, err := address.IDFromAddress(maddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pi := ProvInfo{
|
||||
Addr: maddr,
|
||||
ID: abi.ActorID(mid),
|
||||
}
|
||||
|
||||
claimMap[verifregtypes13.ClaimId(n)] = pi
|
||||
}
|
||||
}
|
||||
|
||||
// If 1 miner ID and multiple arguments
|
||||
if len(miners) == 1 && cctx.Args().Len() > 0 && !all {
|
||||
for _, arg := range cctx.Args().Slice() {
|
||||
detail := strings.Split(arg, "=")
|
||||
if len(detail) > 1 {
|
||||
return xerrors.Errorf("incorrect argument format %s. Must provide only claim IDs with single miner ID", detail)
|
||||
}
|
||||
|
||||
n, err := strconv.ParseInt(detail[0], 10, 64)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to parse the claim ID for %s for argument %s: %s", detail[0], detail, err)
|
||||
}
|
||||
|
||||
claimMap[verifregtypes13.ClaimId(n)] = ProvInfo{}
|
||||
}
|
||||
}
|
||||
|
||||
msgs, err := CreateExtendClaimMsg(ctx, api, claimMap, miners, clientAddr, abi.ChainEpoch(tmax), all, cctx.Bool("assume-yes"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If not msgs are found then no claims can be extended
|
||||
if msgs == nil {
|
||||
fmt.Println("No eligible claims to extend")
|
||||
return nil
|
||||
}
|
||||
|
||||
// MpoolBatchPushMessage method will take care of gas estimation and funds check
|
||||
smsgs, err := api.MpoolBatchPushMessage(ctx, msgs, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// wait for msgs to get mined into a block
|
||||
eg := errgroup.Group{}
|
||||
eg.SetLimit(10)
|
||||
for _, msg := range smsgs {
|
||||
msg := msg
|
||||
eg.Go(func() error {
|
||||
wait, err := api.StateWaitMsg(ctx, msg.Cid(), uint64(cctx.Int("confidence")), 2000, true)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("timeout waiting for message to land on chain %s", wait.Message)
|
||||
|
||||
}
|
||||
|
||||
if wait.Receipt.ExitCode.IsError() {
|
||||
return xerrors.Errorf("failed to execute message %s: %s", wait.Message, wait.Receipt.ExitCode)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return eg.Wait()
|
||||
},
|
||||
}
|
||||
|
||||
type ProvInfo struct {
|
||||
Addr address.Address
|
||||
ID abi.ActorID
|
||||
}
|
||||
|
||||
// CreateExtendClaimMsg creates extend message[s] based on the following conditions
|
||||
// 1. Extend all claims for a miner ID
|
||||
// 2. Extend all claims for multiple miner IDs
|
||||
// 3. Extend specified claims for a miner ID
|
||||
// 4. Extend specific claims for specific miner ID
|
||||
// 5. Extend all claims for a miner ID with different client address (2 messages)
|
||||
// 6. Extend all claims for multiple miner IDs with different client address (2 messages)
|
||||
// 7. Extend specified claims for a miner ID with different client address (2 messages)
|
||||
// 8. Extend specific claims for specific miner ID with different client address (2 messages)
|
||||
func CreateExtendClaimMsg(ctx context.Context, api api.FullNode, pcm map[verifregtypes13.ClaimId]ProvInfo, miners []string, wallet address.Address, tmax abi.ChainEpoch, all, assumeYes bool) ([]*types.Message, error) {
|
||||
|
||||
ac, err := api.StateLookupID(ctx, wallet, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w, err := address.IDFromAddress(ac)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting wallet address to ID: %w", err)
|
||||
}
|
||||
|
||||
wid := abi.ActorID(w)
|
||||
|
||||
head, err := api.ChainHead(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var terms []verifregtypes13.ClaimTerm
|
||||
var newClaims []verifregtypes13.ClaimExtensionRequest
|
||||
rDataCap := big.NewInt(0)
|
||||
|
||||
// If --all is set
|
||||
if all {
|
||||
for _, id := range miners {
|
||||
maddr, err := address.NewFromString(id)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("parsing miner %s: %s", id, err)
|
||||
}
|
||||
mid, err := address.IDFromAddress(maddr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting miner address to miner ID: %s", err)
|
||||
}
|
||||
claims, err := api.StateGetClaims(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting claims for miner %s: %s", maddr, err)
|
||||
}
|
||||
for claimID, claim := range claims {
|
||||
claimID := claimID
|
||||
claim := claim
|
||||
if claim.TermMax < tmax && claim.TermStart+claim.TermMax > head.Height() {
|
||||
// If client is not same - needs to burn datacap
|
||||
if claim.Client != wid {
|
||||
newClaims = append(newClaims, verifregtypes13.ClaimExtensionRequest{
|
||||
Claim: verifregtypes13.ClaimId(claimID),
|
||||
Provider: abi.ActorID(mid),
|
||||
TermMax: tmax,
|
||||
})
|
||||
rDataCap.Add(big.NewInt(int64(claim.Size)).Int, rDataCap.Int)
|
||||
continue
|
||||
}
|
||||
terms = append(terms, verifregtypes13.ClaimTerm{
|
||||
ClaimId: verifregtypes13.ClaimId(claimID),
|
||||
TermMax: tmax,
|
||||
Provider: abi.ActorID(mid),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Single miner and specific claims
|
||||
if len(miners) == 1 && len(pcm) > 0 {
|
||||
maddr, err := address.NewFromString(miners[0])
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("parsing miner %s: %s", miners[0], err)
|
||||
}
|
||||
mid, err := address.IDFromAddress(maddr)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("converting miner address to miner ID: %s", err)
|
||||
}
|
||||
claims, err := api.StateGetClaims(ctx, maddr, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("getting claims for miner %s: %s", maddr, err)
|
||||
}
|
||||
|
||||
for claimID := range pcm {
|
||||
claimID := claimID
|
||||
claim, ok := claims[verifregtypes9.ClaimId(claimID)]
|
||||
if !ok {
|
||||
return nil, xerrors.Errorf("claim %d not found for provider %s", claimID, miners[0])
|
||||
}
|
||||
if claim.TermMax < tmax && claim.TermStart+claim.TermMax > head.Height() {
|
||||
// If client is not same - needs to burn datacap
|
||||
if claim.Client != wid {
|
||||
newClaims = append(newClaims, verifregtypes13.ClaimExtensionRequest{
|
||||
Claim: claimID,
|
||||
Provider: abi.ActorID(mid),
|
||||
TermMax: tmax,
|
||||
})
|
||||
rDataCap.Add(big.NewInt(int64(claim.Size)).Int, rDataCap.Int)
|
||||
continue
|
||||
}
|
||||
terms = append(terms, verifregtypes13.ClaimTerm{
|
||||
ClaimId: claimID,
|
||||
TermMax: tmax,
|
||||
Provider: abi.ActorID(mid),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(miners) == 0 && len(pcm) > 0 {
|
||||
for claimID, prov := range pcm {
|
||||
prov := prov
|
||||
claimID := claimID
|
||||
claim, err := api.StateGetClaim(ctx, prov.Addr, verifregtypes9.ClaimId(claimID), types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("could not load the claim %d: %s", claimID, err)
|
||||
}
|
||||
if claim == nil {
|
||||
return nil, xerrors.Errorf("claim %d not found in the actor state", claimID)
|
||||
}
|
||||
if claim.TermMax < tmax && claim.TermStart+claim.TermMax > head.Height() {
|
||||
// If client is not same - needs to burn datacap
|
||||
if claim.Client != wid {
|
||||
newClaims = append(newClaims, verifregtypes13.ClaimExtensionRequest{
|
||||
Claim: claimID,
|
||||
Provider: prov.ID,
|
||||
TermMax: tmax,
|
||||
})
|
||||
rDataCap.Add(big.NewInt(int64(claim.Size)).Int, rDataCap.Int)
|
||||
continue
|
||||
}
|
||||
terms = append(terms, verifregtypes13.ClaimTerm{
|
||||
ClaimId: claimID,
|
||||
TermMax: tmax,
|
||||
Provider: prov.ID,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var msgs []*types.Message
|
||||
|
||||
if len(terms) > 0 {
|
||||
params, err := actors.SerializeParams(&verifregtypes13.ExtendClaimTermsParams{
|
||||
Terms: terms,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to searialise the parameters: %s", err)
|
||||
}
|
||||
|
||||
oclaimMsg := &types.Message{
|
||||
To: verifreg.Address,
|
||||
From: wallet,
|
||||
Method: verifreg.Methods.ExtendClaimTerms,
|
||||
Params: params,
|
||||
}
|
||||
|
||||
msgs = append(msgs, oclaimMsg)
|
||||
}
|
||||
|
||||
if len(newClaims) > 0 {
|
||||
// Get datacap balance
|
||||
aDataCap, err := api.StateVerifiedClientStatus(ctx, wallet, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if aDataCap == nil {
|
||||
return nil, xerrors.Errorf("wallet %s does not have any datacap", wallet)
|
||||
}
|
||||
|
||||
// Check that we have enough data cap to make the allocation
|
||||
if rDataCap.GreaterThan(big.NewInt(aDataCap.Int64())) {
|
||||
return nil, xerrors.Errorf("requested datacap %s is greater then the available datacap %s", rDataCap, aDataCap)
|
||||
}
|
||||
|
||||
ncparams, err := actors.SerializeParams(&verifregtypes13.AllocationRequests{
|
||||
Extensions: newClaims,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to searialise the parameters: %s", err)
|
||||
}
|
||||
|
||||
transferParams, err := actors.SerializeParams(&datacap2.TransferParams{
|
||||
To: builtin.VerifiedRegistryActorAddr,
|
||||
Amount: big.Mul(rDataCap, builtin.TokenPrecision),
|
||||
OperatorData: ncparams,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to serialize transfer parameters: %s", err)
|
||||
}
|
||||
|
||||
nclaimMsg := &types.Message{
|
||||
To: builtin.DatacapActorAddr,
|
||||
From: wallet,
|
||||
Method: datacap.Methods.TransferExported,
|
||||
Params: transferParams,
|
||||
Value: big.Zero(),
|
||||
}
|
||||
|
||||
if !assumeYes {
|
||||
out := fmt.Sprintf("Some of the specified allocation have a different client address and will require %d Datacap to extend. Proceed? Yes [Y/y] / No [N/n], Ctrl+C (^C) to exit", rDataCap.Int)
|
||||
validate := func(input string) error {
|
||||
if strings.EqualFold(input, "y") || strings.EqualFold(input, "yes") {
|
||||
return nil
|
||||
}
|
||||
if strings.EqualFold(input, "n") || strings.EqualFold(input, "no") {
|
||||
return nil
|
||||
}
|
||||
return errors.New("incorrect input")
|
||||
}
|
||||
|
||||
templates := &promptui.PromptTemplates{
|
||||
Prompt: "{{ . }} ",
|
||||
Valid: "{{ . | green }} ",
|
||||
Invalid: "{{ . | red }} ",
|
||||
Success: "{{ . | cyan | bold }} ",
|
||||
}
|
||||
|
||||
prompt := promptui.Prompt{
|
||||
Label: out,
|
||||
Templates: templates,
|
||||
Validate: validate,
|
||||
}
|
||||
|
||||
input, err := prompt.Run()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if strings.Contains(strings.ToLower(input), "n") {
|
||||
fmt.Println("Dropping the extension for claims that require Datacap")
|
||||
return msgs, nil
|
||||
}
|
||||
}
|
||||
|
||||
msgs = append(msgs, nclaimMsg)
|
||||
}
|
||||
|
||||
return msgs, nil
|
||||
}
|
||||
|
116
cli/util/api.go
116
cli/util/api.go
@ -76,10 +76,22 @@ func GetAPIInfoMulti(ctx *cli.Context, t repo.RepoType) ([]APIInfo, error) {
|
||||
if path == "" {
|
||||
continue
|
||||
}
|
||||
return GetAPIInfoFromRepoPath(path, t)
|
||||
}
|
||||
for _, env := range fallbacksEnvs {
|
||||
env, ok := os.LookupEnv(env)
|
||||
if ok {
|
||||
return ParseApiInfoMulti(env), nil
|
||||
}
|
||||
}
|
||||
|
||||
return []APIInfo{}, fmt.Errorf("could not determine API endpoint for node type: %v. Try setting environment variable: %s", t.Type(), primaryEnv)
|
||||
}
|
||||
|
||||
func GetAPIInfoFromRepoPath(path string, t repo.RepoType) ([]APIInfo, error) {
|
||||
p, err := homedir.Expand(path)
|
||||
if err != nil {
|
||||
return []APIInfo{}, xerrors.Errorf("could not expand home dir (%s): %w", f, err)
|
||||
return []APIInfo{}, xerrors.Errorf("could not expand home dir (%s): %w", path, err)
|
||||
}
|
||||
|
||||
r, err := repo.NewFS(p)
|
||||
@ -112,16 +124,6 @@ func GetAPIInfoMulti(ctx *cli.Context, t repo.RepoType) ([]APIInfo, error) {
|
||||
}}, nil
|
||||
}
|
||||
|
||||
for _, env := range fallbacksEnvs {
|
||||
env, ok := os.LookupEnv(env)
|
||||
if ok {
|
||||
return ParseApiInfoMulti(env), nil
|
||||
}
|
||||
}
|
||||
|
||||
return []APIInfo{}, fmt.Errorf("could not determine API endpoint for node type: %v. Try setting environment variable: %s", t.Type(), primaryEnv)
|
||||
}
|
||||
|
||||
func GetAPIInfo(ctx *cli.Context, t repo.RepoType) (APIInfo, error) {
|
||||
ainfos, err := GetAPIInfoMulti(ctx, t)
|
||||
if err != nil || len(ainfos) == 0 {
|
||||
@ -164,28 +166,6 @@ func GetRawAPIMulti(ctx *cli.Context, t repo.RepoType, version string) ([]HttpHe
|
||||
return httpHeads, nil
|
||||
}
|
||||
|
||||
func GetRawAPIMultiV2(ctx *cli.Context, ainfoCfg []string, version string) ([]HttpHead, error) {
|
||||
var httpHeads []HttpHead
|
||||
|
||||
if len(ainfoCfg) == 0 {
|
||||
return httpHeads, xerrors.Errorf("could not get API info: none configured. \nConsider getting base.toml with './lotus-provider config get base >/tmp/base.toml' \nthen adding \n[APIs] \n ChainApiInfo = [\" result_from lotus auth api-info --perm=admin \"]\n and updating it with './lotus-provider config set /tmp/base.toml'")
|
||||
}
|
||||
for _, i := range ainfoCfg {
|
||||
ainfo := ParseApiInfo(i)
|
||||
addr, err := ainfo.DialArgs(version)
|
||||
if err != nil {
|
||||
return httpHeads, xerrors.Errorf("could not get DialArgs: %w", err)
|
||||
}
|
||||
httpHeads = append(httpHeads, HttpHead{addr: addr, header: ainfo.AuthHeader()})
|
||||
}
|
||||
|
||||
if IsVeryVerbose {
|
||||
_, _ = fmt.Fprintf(ctx.App.Writer, "using raw API %s endpoint: %s\n", version, httpHeads[0].addr)
|
||||
}
|
||||
|
||||
return httpHeads, nil
|
||||
}
|
||||
|
||||
func GetRawAPI(ctx *cli.Context, t repo.RepoType, version string) (string, http.Header, error) {
|
||||
heads, err := GetRawAPIMulti(ctx, t, version)
|
||||
if err != nil {
|
||||
@ -342,14 +322,14 @@ func GetFullNodeAPIV1Single(ctx *cli.Context) (v1api.FullNode, jsonrpc.ClientClo
|
||||
}
|
||||
|
||||
type GetFullNodeOptions struct {
|
||||
ethSubHandler api.EthSubscriber
|
||||
EthSubHandler api.EthSubscriber
|
||||
}
|
||||
|
||||
type GetFullNodeOption func(*GetFullNodeOptions)
|
||||
|
||||
func FullNodeWithEthSubscribtionHandler(sh api.EthSubscriber) GetFullNodeOption {
|
||||
return func(opts *GetFullNodeOptions) {
|
||||
opts.ethSubHandler = sh
|
||||
opts.EthSubHandler = sh
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,8 +344,8 @@ func GetFullNodeAPIV1(ctx *cli.Context, opts ...GetFullNodeOption) (v1api.FullNo
|
||||
}
|
||||
|
||||
var rpcOpts []jsonrpc.Option
|
||||
if options.ethSubHandler != nil {
|
||||
rpcOpts = append(rpcOpts, jsonrpc.WithClientHandler("Filecoin", options.ethSubHandler), jsonrpc.WithClientHandlerAlias("eth_subscription", "Filecoin.EthSubscription"))
|
||||
if options.EthSubHandler != nil {
|
||||
rpcOpts = append(rpcOpts, jsonrpc.WithClientHandler("Filecoin", options.EthSubHandler), jsonrpc.WithClientHandlerAlias("eth_subscription", "Filecoin.EthSubscription"))
|
||||
}
|
||||
|
||||
heads, err := GetRawAPIMulti(ctx, repo.FullNode, "v1")
|
||||
@ -415,68 +395,6 @@ func GetFullNodeAPIV1(ctx *cli.Context, opts ...GetFullNodeOption) (v1api.FullNo
|
||||
return &v1API, finalCloser, nil
|
||||
}
|
||||
|
||||
func GetFullNodeAPIV1LotusProvider(ctx *cli.Context, ainfoCfg []string, opts ...GetFullNodeOption) (v1api.FullNode, jsonrpc.ClientCloser, error) {
|
||||
if tn, ok := ctx.App.Metadata["testnode-full"]; ok {
|
||||
return tn.(v1api.FullNode), func() {}, nil
|
||||
}
|
||||
|
||||
var options GetFullNodeOptions
|
||||
for _, opt := range opts {
|
||||
opt(&options)
|
||||
}
|
||||
|
||||
var rpcOpts []jsonrpc.Option
|
||||
if options.ethSubHandler != nil {
|
||||
rpcOpts = append(rpcOpts, jsonrpc.WithClientHandler("Filecoin", options.ethSubHandler), jsonrpc.WithClientHandlerAlias("eth_subscription", "Filecoin.EthSubscription"))
|
||||
}
|
||||
|
||||
heads, err := GetRawAPIMultiV2(ctx, ainfoCfg, "v1")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if IsVeryVerbose {
|
||||
_, _ = fmt.Fprintln(ctx.App.Writer, "using full node API v1 endpoint:", heads[0].addr)
|
||||
}
|
||||
|
||||
var fullNodes []api.FullNode
|
||||
var closers []jsonrpc.ClientCloser
|
||||
|
||||
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, Reason: %s", head.addr, err.Error())
|
||||
continue
|
||||
}
|
||||
fullNodes = append(fullNodes, v1api)
|
||||
closers = append(closers, closer)
|
||||
}
|
||||
|
||||
// When running in cluster mode and trying to establish connections to multiple nodes, fail
|
||||
// if less than 2 lotus nodes are actually running
|
||||
if len(heads) > 1 && len(fullNodes) < 2 {
|
||||
return nil, nil, xerrors.Errorf("Not able to establish connection to more than a single node")
|
||||
}
|
||||
|
||||
finalCloser := func() {
|
||||
for _, c := range closers {
|
||||
c()
|
||||
}
|
||||
}
|
||||
|
||||
var v1API api.FullNodeStruct
|
||||
FullNodeProxy(fullNodes, &v1API)
|
||||
|
||||
v, err := v1API.Version(ctx.Context)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !v.APIVersion.EqMajorMinor(api.FullAPIVersion1) {
|
||||
return nil, nil, xerrors.Errorf("Remote API version didn't match (expected %s, remote %s)", api.FullAPIVersion1, v.APIVersion)
|
||||
}
|
||||
return &v1API, finalCloser, nil
|
||||
}
|
||||
|
||||
type GetStorageMinerOptions struct {
|
||||
PreferHttp bool
|
||||
}
|
||||
|
@ -18,11 +18,11 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/rpc"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/rpc"
|
||||
)
|
||||
|
||||
const providerEnvVar = "PROVIDER_API_INFO"
|
||||
const providerEnvVar = "CURIO_API_INFO"
|
||||
|
||||
var cliCmd = &cli.Command{
|
||||
Name: "cli",
|
||||
@ -177,7 +177,7 @@ var cliCmd = &cli.Command{
|
||||
}
|
||||
|
||||
{
|
||||
api, closer, err := rpc.GetProviderAPI(cctx)
|
||||
api, closer, err := rpc.GetCurioAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
@ -15,7 +15,7 @@ import (
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
)
|
||||
@ -48,7 +48,7 @@ var configDefaultCmd = &cli.Command{
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
comment := !cctx.Bool("no-comment")
|
||||
cfg, err := getDefaultConfig(comment)
|
||||
cfg, err := deps.GetDefaultConfig(comment)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -58,15 +58,6 @@ var configDefaultCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func getDefaultConfig(comment bool) (string, error) {
|
||||
c := config.DefaultLotusProvider()
|
||||
cb, err := config.ConfigUpdate(c, nil, config.Commented(comment), config.DefaultKeepUncommented(), config.NoEnv())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(cb), nil
|
||||
}
|
||||
|
||||
var configSetCmd = &cli.Command{
|
||||
Name: "set",
|
||||
Aliases: []string{"add", "update", "create"},
|
||||
@ -106,12 +97,12 @@ var configSetCmd = &cli.Command{
|
||||
return fmt.Errorf("cannot read stream/file %w", err)
|
||||
}
|
||||
|
||||
lp := config.DefaultLotusProvider() // ensure it's toml
|
||||
_, err = deps.LoadConfigWithUpgrades(string(bytes), lp)
|
||||
curioConfig := config.DefaultCurioConfig() // ensure it's toml
|
||||
_, err = deps.LoadConfigWithUpgrades(string(bytes), curioConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot decode file: %w", err)
|
||||
}
|
||||
_ = lp
|
||||
_ = curioConfig
|
||||
|
||||
err = setConfig(db, name, string(bytes))
|
||||
|
||||
@ -216,7 +207,7 @@ var configRmCmd = &cli.Command{
|
||||
var configViewCmd = &cli.Command{
|
||||
Name: "interpret",
|
||||
Aliases: []string{"view", "stacked", "stack"},
|
||||
Usage: "Interpret stacked config layers by this version of lotus-provider, with system-generated comments.",
|
||||
Usage: "Interpret stacked config layers by this version of curio, with system-generated comments.",
|
||||
ArgsUsage: "a list of layers to be interpreted as the final config",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringSliceFlag{
|
||||
@ -230,11 +221,11 @@ var configViewCmd = &cli.Command{
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lp, err := deps.GetConfig(cctx, db)
|
||||
curioConfig, err := deps.GetConfig(cctx, db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cb, err := config.ConfigUpdate(lp, config.DefaultLotusProvider(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv())
|
||||
cb, err := config.ConfigUpdate(curioConfig, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("cannot interpret config: %w", err)
|
||||
}
|
||||
@ -299,12 +290,12 @@ var configEditCmd = &cli.Command{
|
||||
}
|
||||
|
||||
if cctx.IsSet("source") && source != layer && !cctx.Bool("no-interpret-source") {
|
||||
lp := config.DefaultLotusProvider()
|
||||
lp := config.DefaultCurioConfig()
|
||||
if _, err := toml.Decode(sourceConfig, lp); err != nil {
|
||||
return xerrors.Errorf("parsing source config: %w", err)
|
||||
}
|
||||
|
||||
cb, err := config.ConfigUpdate(lp, config.DefaultLotusProvider(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv())
|
||||
cb, err := config.ConfigUpdate(lp, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv())
|
||||
if err != nil {
|
||||
return xerrors.Errorf("interpreting source config: %w", err)
|
||||
}
|
||||
@ -362,9 +353,18 @@ var configEditCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func getDefaultConfig(comment bool) (string, error) {
|
||||
c := config.DefaultCurioConfig()
|
||||
cb, err := config.ConfigUpdate(c, nil, config.Commented(comment), config.DefaultKeepUncommented(), config.NoEnv())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(cb), nil
|
||||
}
|
||||
|
||||
func diff(sourceConf, newConf string) (string, error) {
|
||||
lpSrc := config.DefaultLotusProvider()
|
||||
lpNew := config.DefaultLotusProvider()
|
||||
lpSrc := config.DefaultCurioConfig()
|
||||
lpNew := config.DefaultCurioConfig()
|
||||
|
||||
_, err := toml.Decode(sourceConf, lpSrc)
|
||||
if err != nil {
|
@ -18,7 +18,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
)
|
||||
@ -73,7 +73,7 @@ var configNewCmd = &cli.Command{
|
||||
msg := "Layer " + configColor(name) + ` created. `
|
||||
|
||||
// setup config
|
||||
lpCfg := config.DefaultLotusProvider()
|
||||
lpCfg := config.DefaultCurioConfig()
|
||||
|
||||
for _, addr := range cctx.Args().Slice() {
|
||||
maddr, err := address.NewFromString(addr)
|
||||
@ -86,7 +86,7 @@ var configNewCmd = &cli.Command{
|
||||
return xerrors.Errorf("Failed to get miner info: %w", err)
|
||||
}
|
||||
|
||||
lpCfg.Addresses = append(lpCfg.Addresses, config.LotusProviderAddresses{
|
||||
lpCfg.Addresses = append(lpCfg.Addresses, config.CurioAddresses{
|
||||
PreCommitControl: nil,
|
||||
CommitControl: nil,
|
||||
TerminateControl: nil,
|
94
cmd/curio/deps/apiinfo.go
Normal file
94
cmd/curio/deps/apiinfo.go
Normal file
@ -0,0 +1,94 @@
|
||||
package deps
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-jsonrpc"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/client"
|
||||
"github.com/filecoin-project/lotus/api/v1api"
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
)
|
||||
|
||||
func getFullNodeAPIV1Curio(ctx *cli.Context, ainfoCfg []string, opts ...cliutil.GetFullNodeOption) (v1api.FullNode, jsonrpc.ClientCloser, error) {
|
||||
if tn, ok := ctx.App.Metadata["testnode-full"]; ok {
|
||||
return tn.(v1api.FullNode), func() {}, nil
|
||||
}
|
||||
|
||||
var options cliutil.GetFullNodeOptions
|
||||
for _, opt := range opts {
|
||||
opt(&options)
|
||||
}
|
||||
|
||||
var rpcOpts []jsonrpc.Option
|
||||
if options.EthSubHandler != nil {
|
||||
rpcOpts = append(rpcOpts, jsonrpc.WithClientHandler("Filecoin", options.EthSubHandler), jsonrpc.WithClientHandlerAlias("eth_subscription", "Filecoin.EthSubscription"))
|
||||
}
|
||||
|
||||
var httpHeads []httpHead
|
||||
version := "v1"
|
||||
{
|
||||
if len(ainfoCfg) == 0 {
|
||||
return nil, nil, xerrors.Errorf("could not get API info: none configured. \nConsider getting base.toml with './curio config get base >/tmp/base.toml' \nthen adding \n[APIs] \n ChainApiInfo = [\" result_from lotus auth api-info --perm=admin \"]\n and updating it with './curio config set /tmp/base.toml'")
|
||||
}
|
||||
for _, i := range ainfoCfg {
|
||||
ainfo := cliutil.ParseApiInfo(i)
|
||||
addr, err := ainfo.DialArgs(version)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("could not get DialArgs: %w", err)
|
||||
}
|
||||
httpHeads = append(httpHeads, httpHead{addr: addr, header: ainfo.AuthHeader()})
|
||||
}
|
||||
}
|
||||
|
||||
if cliutil.IsVeryVerbose {
|
||||
_, _ = fmt.Fprintln(ctx.App.Writer, "using full node API v1 endpoint:", httpHeads[0].addr)
|
||||
}
|
||||
|
||||
var fullNodes []api.FullNode
|
||||
var closers []jsonrpc.ClientCloser
|
||||
|
||||
for _, head := range httpHeads {
|
||||
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, Reason: %s", head.addr, err.Error())
|
||||
continue
|
||||
}
|
||||
fullNodes = append(fullNodes, v1api)
|
||||
closers = append(closers, closer)
|
||||
}
|
||||
|
||||
// When running in cluster mode and trying to establish connections to multiple nodes, fail
|
||||
// if less than 2 lotus nodes are actually running
|
||||
if len(httpHeads) > 1 && len(fullNodes) < 2 {
|
||||
return nil, nil, xerrors.Errorf("Not able to establish connection to more than a single node")
|
||||
}
|
||||
|
||||
finalCloser := func() {
|
||||
for _, c := range closers {
|
||||
c()
|
||||
}
|
||||
}
|
||||
|
||||
var v1API api.FullNodeStruct
|
||||
cliutil.FullNodeProxy(fullNodes, &v1API)
|
||||
|
||||
v, err := v1API.Version(ctx.Context)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !v.APIVersion.EqMajorMinor(api.FullAPIVersion1) {
|
||||
return nil, nil, xerrors.Errorf("Remote API version didn't match (expected %s, remote %s)", api.FullAPIVersion1, v.APIVersion)
|
||||
}
|
||||
return &v1API, finalCloser, nil
|
||||
}
|
||||
|
||||
type httpHead struct {
|
||||
addr string
|
||||
header http.Header
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Package deps provides the dependencies for the lotus provider node.
|
||||
// Package deps provides the dependencies for the curio node.
|
||||
package deps
|
||||
|
||||
import (
|
||||
@ -9,8 +9,9 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
@ -18,6 +19,7 @@ import (
|
||||
ds "github.com/ipfs/go-datastore"
|
||||
dssync "github.com/ipfs/go-datastore/sync"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"github.com/samber/lo"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
@ -27,7 +29,8 @@ import (
|
||||
"github.com/filecoin-project/go-statestore"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
curio "github.com/filecoin-project/lotus/curiosrc"
|
||||
"github.com/filecoin-project/lotus/curiosrc/multictladdr"
|
||||
"github.com/filecoin-project/lotus/journal"
|
||||
"github.com/filecoin-project/lotus/journal/alerting"
|
||||
"github.com/filecoin-project/lotus/journal/fsjournal"
|
||||
@ -36,17 +39,17 @@ import (
|
||||
"github.com/filecoin-project/lotus/node/modules"
|
||||
"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/multictladdr"
|
||||
"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"
|
||||
)
|
||||
|
||||
var log = logging.Logger("lotus-provider/deps")
|
||||
var log = logging.Logger("curio/deps")
|
||||
|
||||
func MakeDB(cctx *cli.Context) (*harmonydb.DB, error) {
|
||||
// #1 CLI opts
|
||||
fromCLI := func() (*harmonydb.DB, error) {
|
||||
dbConfig := config.HarmonyDB{
|
||||
Username: cctx.String("db-user"),
|
||||
Password: cctx.String("db-password"),
|
||||
@ -57,6 +60,71 @@ func MakeDB(cctx *cli.Context) (*harmonydb.DB, error) {
|
||||
return harmonydb.NewFromConfig(dbConfig)
|
||||
}
|
||||
|
||||
readToml := func(path string) (*harmonydb.DB, error) {
|
||||
cfg, err := config.FromFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if c, ok := cfg.(*config.StorageMiner); ok {
|
||||
return harmonydb.NewFromConfig(c.HarmonyDB)
|
||||
}
|
||||
return nil, errors.New("not a miner config")
|
||||
}
|
||||
|
||||
// #2 Try local miner config
|
||||
fromMinerEnv := func() (*harmonydb.DB, error) {
|
||||
v := os.Getenv("LOTUS_MINER_PATH")
|
||||
if v == "" {
|
||||
return nil, errors.New("no miner env")
|
||||
}
|
||||
return readToml(filepath.Join(v, "config.toml"))
|
||||
|
||||
}
|
||||
|
||||
fromMiner := func() (*harmonydb.DB, error) {
|
||||
u, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return readToml(filepath.Join(u, ".lotusminer/config.toml"))
|
||||
}
|
||||
fromEnv := func() (*harmonydb.DB, error) {
|
||||
// #3 Try env
|
||||
u, err := url.Parse(os.Getenv("CURIO_DB"))
|
||||
if err != nil {
|
||||
return nil, errors.New("no db connection string found in CURIO_DB env")
|
||||
}
|
||||
cfg := config.DefaultStorageMiner().HarmonyDB
|
||||
if u.User.Username() != "" {
|
||||
cfg.Username = u.User.Username()
|
||||
}
|
||||
if p, ok := u.User.Password(); ok && p != "" {
|
||||
cfg.Password = p
|
||||
}
|
||||
if u.Hostname() != "" {
|
||||
cfg.Hosts = []string{u.Hostname()}
|
||||
}
|
||||
if u.Port() != "" {
|
||||
cfg.Port = u.Port()
|
||||
}
|
||||
if strings.TrimPrefix(u.Path, "/") != "" {
|
||||
cfg.Database = strings.TrimPrefix(u.Path, "/")
|
||||
}
|
||||
|
||||
return harmonydb.NewFromConfig(cfg)
|
||||
}
|
||||
|
||||
for _, f := range []func() (*harmonydb.DB, error){fromCLI, fromMinerEnv, fromMiner, fromEnv} {
|
||||
db, err := f()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
log.Error("No db connection string found. User CLI args or env var: set CURIO_DB=postgres://USER:PASSWORD@HOST:PORT/DATABASE")
|
||||
return fromCLI() //in-case it's not about bad config.
|
||||
}
|
||||
|
||||
type JwtPayload struct {
|
||||
Allow []auth.Permission
|
||||
}
|
||||
@ -93,8 +161,8 @@ func GetDeps(ctx context.Context, cctx *cli.Context) (*Deps, error) {
|
||||
}
|
||||
|
||||
type Deps struct {
|
||||
Cfg *config.LotusProviderConfig
|
||||
DB *harmonydb.DB
|
||||
Cfg *config.CurioConfig // values
|
||||
DB *harmonydb.DB // has itest capability
|
||||
Full api.FullNode
|
||||
Verif storiface.Verifier
|
||||
LW *sealer.LocalWorker
|
||||
@ -128,7 +196,7 @@ func (deps *Deps) PopulateRemainingDeps(ctx context.Context, cctx *cli.Context,
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
if err := r.Init(repo.Provider); err != nil {
|
||||
if err := r.Init(repo.Curio); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -156,7 +224,7 @@ func (deps *Deps) PopulateRemainingDeps(ctx context.Context, cctx *cli.Context,
|
||||
}
|
||||
|
||||
if deps.As == nil {
|
||||
deps.As, err = provider.AddressSelector(deps.Cfg.Addresses)()
|
||||
deps.As, err = curio.AddressSelector(deps.Cfg.Addresses)()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -186,7 +254,7 @@ func (deps *Deps) PopulateRemainingDeps(ctx context.Context, cctx *cli.Context,
|
||||
if v := os.Getenv("FULLNODE_API_INFO"); v != "" {
|
||||
cfgApiInfo = []string{v}
|
||||
}
|
||||
deps.Full, fullCloser, err = cliutil.GetFullNodeAPIV1LotusProvider(cctx, cfgApiInfo)
|
||||
deps.Full, fullCloser, err = getFullNodeAPIV1Curio(cctx, cfgApiInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -236,7 +304,7 @@ Get it with: jq .PrivateKey ~/.lotus-miner/keystore/MF2XI2BNNJ3XILLQOJUXMYLUMU`,
|
||||
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
|
||||
// maybe with a curio 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{
|
||||
MaxParallelChallengeReads: deps.Cfg.Proving.ParallelCheckLimit,
|
||||
@ -273,21 +341,30 @@ Get it with: jq .PrivateKey ~/.lotus-miner/keystore/MF2XI2BNNJ3XILLQOJUXMYLUMU`,
|
||||
return nil
|
||||
}
|
||||
|
||||
var oldAddresses = regexp.MustCompile("(?i)^\\[addresses\\]$")
|
||||
|
||||
func LoadConfigWithUpgrades(text string, lp *config.LotusProviderConfig) (toml.MetaData, error) {
|
||||
func LoadConfigWithUpgrades(text string, curioConfigWithDefaults *config.CurioConfig) (toml.MetaData, error) {
|
||||
// allow migration from old config format that was limited to 1 wallet setup.
|
||||
newText := oldAddresses.ReplaceAllString(text, "[[addresses]]")
|
||||
|
||||
if text != newText {
|
||||
log.Warnw("Upgraded config!", "old", text, "new", newText)
|
||||
newText := strings.Join(lo.Map(strings.Split(text, "\n"), func(line string, _ int) string {
|
||||
if strings.EqualFold(line, "[addresses]") {
|
||||
return "[[addresses]]"
|
||||
}
|
||||
return line
|
||||
}), "\n")
|
||||
meta, err := toml.Decode(newText, &curioConfigWithDefaults)
|
||||
for i := range curioConfigWithDefaults.Addresses {
|
||||
if curioConfigWithDefaults.Addresses[i].PreCommitControl == nil {
|
||||
curioConfigWithDefaults.Addresses[i].PreCommitControl = []string{}
|
||||
}
|
||||
if curioConfigWithDefaults.Addresses[i].CommitControl == nil {
|
||||
curioConfigWithDefaults.Addresses[i].CommitControl = []string{}
|
||||
}
|
||||
if curioConfigWithDefaults.Addresses[i].TerminateControl == nil {
|
||||
curioConfigWithDefaults.Addresses[i].TerminateControl = []string{}
|
||||
}
|
||||
}
|
||||
|
||||
meta, err := toml.Decode(newText, &lp)
|
||||
return meta, err
|
||||
}
|
||||
func GetConfig(cctx *cli.Context, db *harmonydb.DB) (*config.LotusProviderConfig, error) {
|
||||
lp := config.DefaultLotusProvider()
|
||||
func GetConfig(cctx *cli.Context, db *harmonydb.DB) (*config.CurioConfig, error) {
|
||||
curioConfig := config.DefaultCurioConfig()
|
||||
have := []string{}
|
||||
layers := append([]string{"base"}, cctx.StringSlice("layers")...) // Always stack on top of "base" layer
|
||||
for _, layer := range layers {
|
||||
@ -298,26 +375,35 @@ func GetConfig(cctx *cli.Context, db *harmonydb.DB) (*config.LotusProviderConfig
|
||||
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, errors.New(`curio defaults to a layer named 'base'.
|
||||
Either use 'migrate' command or edit a base.toml and upload it with: curio config set base.toml`)
|
||||
}
|
||||
return nil, fmt.Errorf("could not read layer '%s': %w", layer, err)
|
||||
}
|
||||
|
||||
meta, err := LoadConfigWithUpgrades(text, lp)
|
||||
meta, err := LoadConfigWithUpgrades(text, curioConfig)
|
||||
if err != nil {
|
||||
return lp, fmt.Errorf("could not read layer, bad toml %s: %w", layer, err)
|
||||
return curioConfig, fmt.Errorf("could not read layer, bad toml %s: %w", layer, err)
|
||||
}
|
||||
for _, k := range meta.Keys() {
|
||||
have = append(have, strings.Join(k, " "))
|
||||
}
|
||||
log.Infow("Using layer", "layer", layer, "config", lp)
|
||||
log.Infow("Using layer", "layer", layer, "config", curioConfig)
|
||||
}
|
||||
_ = 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
|
||||
return curioConfig, nil
|
||||
}
|
||||
|
||||
func GetDefaultConfig(comment bool) (string, error) {
|
||||
c := config.DefaultCurioConfig()
|
||||
cb, err := config.ConfigUpdate(c, nil, config.Commented(comment), config.DefaultKeepUncommented(), config.NoEnv())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(cb), nil
|
||||
}
|
||||
|
||||
func GetDepsCLI(ctx context.Context, cctx *cli.Context) (*Deps, error) {
|
||||
@ -331,7 +417,7 @@ func GetDepsCLI(ctx context.Context, cctx *cli.Context) (*Deps, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
full, fullCloser, err := cliutil.GetFullNodeAPIV1LotusProvider(cctx, cfg.Apis.ChainApiInfo)
|
||||
full, fullCloser, err := getFullNodeAPIV1Curio(cctx, cfg.Apis.ChainApiInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
590
cmd/curio/guidedsetup/guidedsetup.go
Normal file
590
cmd/curio/guidedsetup/guidedsetup.go
Normal file
@ -0,0 +1,590 @@
|
||||
// guidedSetup for migration from lotus-miner to Curio
|
||||
//
|
||||
// IF STRINGS CHANGED {
|
||||
// follow instructions at ../internal/translations/translations.go
|
||||
// }
|
||||
package guidedsetup
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/bits"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/manifoldco/promptui"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/samber/lo"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-jsonrpc"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/v0api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
_ "github.com/filecoin-project/lotus/cmd/curio/internal/translations"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
)
|
||||
|
||||
// URL to upload user-selected fields to help direct developer's focus.
|
||||
const DeveloperFocusRequestURL = "https://curiostorage.org/cgi-bin/savedata.php"
|
||||
|
||||
var GuidedsetupCmd = &cli.Command{
|
||||
Name: "guided-setup",
|
||||
Usage: "Run the guided setup for migrating from lotus-miner to Curio",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{ // for cliutil.GetFullNodeAPI
|
||||
Name: "repo",
|
||||
EnvVars: []string{"LOTUS_PATH"},
|
||||
Hidden: true,
|
||||
Value: "~/.lotus",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) (err error) {
|
||||
T, say := SetupLanguage()
|
||||
setupCtrlC(say)
|
||||
|
||||
say(header, "This interactive tool migrates lotus-miner to Curio in 5 minutes.")
|
||||
say(notice, "Each step needs your confirmation and can be reversed. Press Ctrl+C to exit at any time.")
|
||||
|
||||
// Run the migration steps
|
||||
migrationData := MigrationData{
|
||||
T: T,
|
||||
say: say,
|
||||
selectTemplates: &promptui.SelectTemplates{
|
||||
Help: T("Use the arrow keys to navigate: ↓ ↑ → ← "),
|
||||
},
|
||||
cctx: cctx,
|
||||
}
|
||||
for _, step := range migrationSteps {
|
||||
step(&migrationData)
|
||||
}
|
||||
for _, closer := range migrationData.closers {
|
||||
closer()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func setupCtrlC(say func(style lipgloss.Style, key message.Reference, a ...interface{})) {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-c
|
||||
say(notice, "Ctrl+C pressed in Terminal")
|
||||
os.Exit(2)
|
||||
}()
|
||||
}
|
||||
|
||||
var (
|
||||
header = lipgloss.NewStyle().
|
||||
Align(lipgloss.Left).
|
||||
Foreground(lipgloss.Color("#00FF00")).
|
||||
Background(lipgloss.Color("#242424")).
|
||||
BorderStyle(lipgloss.NormalBorder()).
|
||||
Width(60).Margin(1)
|
||||
|
||||
notice = lipgloss.NewStyle().
|
||||
Align(lipgloss.Left).
|
||||
Bold(true).
|
||||
Foreground(lipgloss.Color("#CCCCCC")).
|
||||
Background(lipgloss.Color("#333300")).MarginBottom(1)
|
||||
|
||||
green = lipgloss.NewStyle().
|
||||
Align(lipgloss.Left).
|
||||
Foreground(lipgloss.Color("#00FF00")).
|
||||
Background(lipgloss.Color("#000000"))
|
||||
|
||||
plain = lipgloss.NewStyle().Align(lipgloss.Left)
|
||||
|
||||
section = lipgloss.NewStyle().
|
||||
Align(lipgloss.Left).
|
||||
Foreground(lipgloss.Color("#000000")).
|
||||
Background(lipgloss.Color("#FFFFFF")).
|
||||
Underline(true)
|
||||
|
||||
code = lipgloss.NewStyle().
|
||||
Align(lipgloss.Left).
|
||||
Foreground(lipgloss.Color("#00FF00")).
|
||||
Background(lipgloss.Color("#f8f9fa"))
|
||||
)
|
||||
|
||||
func SetupLanguage() (func(key message.Reference, a ...interface{}) string, func(style lipgloss.Style, key message.Reference, a ...interface{})) {
|
||||
langText := "en"
|
||||
problem := false
|
||||
if len(os.Getenv("LANG")) > 1 {
|
||||
langText = os.Getenv("LANG")[:2]
|
||||
} else {
|
||||
problem = true
|
||||
}
|
||||
|
||||
lang, err := language.Parse(langText)
|
||||
if err != nil {
|
||||
lang = language.English
|
||||
problem = true
|
||||
fmt.Println("Error parsing language")
|
||||
}
|
||||
|
||||
langs := message.DefaultCatalog.Languages()
|
||||
have := lo.SliceToMap(langs, func(t language.Tag) (string, bool) { return t.String(), true })
|
||||
if _, ok := have[lang.String()]; !ok {
|
||||
lang = language.English
|
||||
problem = true
|
||||
}
|
||||
if problem {
|
||||
_ = os.Setenv("LANG", "en-US") // for later users of this function
|
||||
notice.Copy().AlignHorizontal(lipgloss.Right).
|
||||
Render("$LANG=" + langText + " unsupported. Available: " + strings.Join(lo.Keys(have), ", "))
|
||||
fmt.Println("Defaulting to English. Please reach out to the Curio team if you would like to have additional language support.")
|
||||
}
|
||||
return func(key message.Reference, a ...interface{}) string {
|
||||
return message.NewPrinter(lang).Sprintf(key, a...)
|
||||
}, func(sty lipgloss.Style, key message.Reference, a ...interface{}) {
|
||||
msg := message.NewPrinter(lang).Sprintf(key, a...)
|
||||
fmt.Println(sty.Render(msg))
|
||||
}
|
||||
}
|
||||
|
||||
type migrationStep func(*MigrationData)
|
||||
|
||||
var migrationSteps = []migrationStep{
|
||||
readMinerConfig, // Tells them to be on the miner machine
|
||||
yugabyteConnect, // Miner is updated
|
||||
configToDB, // work on base configuration migration.
|
||||
verifySectors, // Verify the sectors are in the database
|
||||
doc,
|
||||
oneLastThing,
|
||||
complete,
|
||||
}
|
||||
|
||||
type MigrationData struct {
|
||||
T func(key message.Reference, a ...interface{}) string
|
||||
say func(style lipgloss.Style, key message.Reference, a ...interface{})
|
||||
selectTemplates *promptui.SelectTemplates
|
||||
MinerConfigPath string
|
||||
MinerConfig *config.StorageMiner
|
||||
DB *harmonydb.DB
|
||||
MinerID address.Address
|
||||
full v0api.FullNode
|
||||
cctx *cli.Context
|
||||
closers []jsonrpc.ClientCloser
|
||||
}
|
||||
|
||||
func complete(d *MigrationData) {
|
||||
stepCompleted(d, d.T("Lotus-Miner to Curio Migration."))
|
||||
d.say(plain, "Try the web interface with %s for further guided improvements.", "--layers=gui")
|
||||
d.say(plain, "You can now migrate your market node (%s), if applicable.", "Boost")
|
||||
}
|
||||
func configToDB(d *MigrationData) {
|
||||
d.say(section, "Migrating lotus-miner config.toml to Curio in-database configuration.")
|
||||
|
||||
{
|
||||
var closer jsonrpc.ClientCloser
|
||||
var err error
|
||||
d.full, closer, err = cliutil.GetFullNodeAPI(d.cctx)
|
||||
d.closers = append(d.closers, closer)
|
||||
if err != nil {
|
||||
d.say(notice, "Error getting API: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
ainfo, err := cliutil.GetAPIInfo(d.cctx, repo.FullNode)
|
||||
if err != nil {
|
||||
d.say(notice, "could not get API info for FullNode: %w", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
token, err := d.full.AuthNew(context.Background(), api.AllPermissions)
|
||||
if err != nil {
|
||||
d.say(notice, "Error getting token: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
chainApiInfo := fmt.Sprintf("%s:%s", string(token), ainfo.Addr)
|
||||
|
||||
d.MinerID, err = SaveConfigToLayer(d.MinerConfigPath, "", false, chainApiInfo)
|
||||
if err != nil {
|
||||
d.say(notice, "Error saving config to layer: %s. Aborting Migration", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// bucket returns the power's 4 highest bits (rounded down).
|
||||
func bucket(power *api.MinerPower) uint64 {
|
||||
rawQAP := power.TotalPower.QualityAdjPower.Uint64()
|
||||
magnitude := lo.Max([]int{bits.Len64(rawQAP), 5})
|
||||
|
||||
// shifting erases resolution so we cannot distinguish SPs of similar scales.
|
||||
return rawQAP >> (uint64(magnitude) - 4) << (uint64(magnitude - 4))
|
||||
}
|
||||
|
||||
type uploadType int
|
||||
|
||||
const uploadTypeIndividual uploadType = 0
|
||||
const uploadTypeAggregate uploadType = 1
|
||||
|
||||
// const uploadTypeHint uploadType = 2
|
||||
const uploadTypeNothing uploadType = 3
|
||||
|
||||
func oneLastThing(d *MigrationData) {
|
||||
d.say(section, "The Curio team wants to improve the software you use. Tell the team you're using `%s`.", "curio")
|
||||
i, _, err := (&promptui.Select{
|
||||
Label: d.T("Select what you want to share with the Curio team."),
|
||||
Items: []string{
|
||||
d.T("Individual Data: Miner ID, Curio version, chain (%s or %s). Signed.", "mainnet", "calibration"),
|
||||
d.T("Aggregate-Anonymous: version, chain, and Miner power (bucketed)."),
|
||||
d.T("Hint: I am someone running Curio on whichever chain."),
|
||||
d.T("Nothing.")},
|
||||
Templates: d.selectTemplates,
|
||||
}).Run()
|
||||
preference := uploadType(i)
|
||||
if err != nil {
|
||||
d.say(notice, "Aborting remaining steps.", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
if preference != uploadTypeNothing {
|
||||
msgMap := map[string]any{
|
||||
"domain": "curio-newuser",
|
||||
"net": build.BuildTypeString(),
|
||||
}
|
||||
if preference == uploadTypeIndividual || preference == uploadTypeAggregate {
|
||||
// articles of incorporation
|
||||
power, err := d.full.StateMinerPower(context.Background(), d.MinerID, types.EmptyTSK)
|
||||
if err != nil {
|
||||
d.say(notice, "Error getting miner power: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
msgMap["version"] = build.BuildVersion
|
||||
msgMap["net"] = build.BuildType
|
||||
msgMap["power"] = map[uploadType]uint64{
|
||||
uploadTypeIndividual: power.MinerPower.QualityAdjPower.Uint64(),
|
||||
uploadTypeAggregate: bucket(power)}[preference]
|
||||
|
||||
if preference == uploadTypeIndividual { // Sign it
|
||||
msgMap["miner_id"] = d.MinerID
|
||||
msg, err := json.Marshal(msgMap)
|
||||
if err != nil {
|
||||
d.say(notice, "Error marshalling message: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
mi, err := d.full.StateMinerInfo(context.Background(), d.MinerID, types.EmptyTSK)
|
||||
if err != nil {
|
||||
d.say(notice, "Error getting miner info: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
sig, err := d.full.WalletSign(context.Background(), mi.Worker, msg)
|
||||
if err != nil {
|
||||
d.say(notice, "Error signing message: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
msgMap["signature"] = base64.StdEncoding.EncodeToString(sig.Data)
|
||||
}
|
||||
}
|
||||
msg, err := json.Marshal(msgMap)
|
||||
if err != nil {
|
||||
d.say(notice, "Error marshalling message: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Post(DeveloperFocusRequestURL, "application/json", bytes.NewReader(msg))
|
||||
if err != nil {
|
||||
d.say(notice, "Error sending message: %s", err.Error())
|
||||
}
|
||||
if resp != nil {
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
if resp.StatusCode != 200 {
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err == nil {
|
||||
d.say(notice, "Error sending message: Status %s, Message: ", resp.Status, string(b))
|
||||
}
|
||||
} else {
|
||||
stepCompleted(d, d.T("Message sent."))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func doc(d *MigrationData) {
|
||||
d.say(plain, "Documentation: ")
|
||||
d.say(plain, "The '%s' layer stores common configuration. All curio instances can include it in their %s argument.", "base", "--layers")
|
||||
d.say(plain, "You can add other layers for per-machine configuration changes.")
|
||||
|
||||
d.say(plain, "Filecoin %s channels: %s and %s", "Slack", "#fil-curio-help", "#fil-curio-dev")
|
||||
|
||||
d.say(plain, "Start multiple Curio instances with the '%s' layer to redundancy.", "post")
|
||||
//d.say(plain, "Point your browser to your web GUI to complete setup with %s and advanced featues.", "Boost")
|
||||
d.say(plain, "One database can serve multiple miner IDs: Run a migration for each lotus-miner.")
|
||||
}
|
||||
|
||||
func verifySectors(d *MigrationData) {
|
||||
var i []int
|
||||
var lastError string
|
||||
fmt.Println()
|
||||
d.say(section, "Please start (or restart) %s now that database credentials are in %s.", "lotus-miner", "config.toml")
|
||||
d.say(notice, "Waiting for %s to write sectors into Yugabyte.", "lotus-miner")
|
||||
|
||||
mid, err := address.IDFromAddress(d.MinerID)
|
||||
if err != nil {
|
||||
d.say(notice, "Error interpreting miner ID: %s: ID: %s", err.Error(), d.MinerID.String())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for {
|
||||
err := d.DB.Select(context.Background(), &i, `
|
||||
SELECT count(*) FROM sector_location WHERE miner_id=$1`, mid)
|
||||
if err != nil {
|
||||
if err.Error() != lastError {
|
||||
d.say(notice, "Error verifying sectors: %s", err.Error())
|
||||
lastError = err.Error()
|
||||
}
|
||||
continue
|
||||
}
|
||||
if i[0] > 0 {
|
||||
break
|
||||
}
|
||||
fmt.Print(".")
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
d.say(plain, "The sectors are in the database. The database is ready for %s.", "Curio")
|
||||
d.say(notice, "Now shut down lotus-miner and move the systems to %s.", "Curio")
|
||||
|
||||
_, err = (&promptui.Prompt{Label: d.T("Press return to continue")}).Run()
|
||||
if err != nil {
|
||||
d.say(notice, "Aborting migration.")
|
||||
os.Exit(1)
|
||||
}
|
||||
stepCompleted(d, d.T("Sectors verified. %d sector locations found.", i))
|
||||
}
|
||||
|
||||
func yugabyteConnect(d *MigrationData) {
|
||||
harmonyCfg := config.DefaultStorageMiner().HarmonyDB //copy the config to a local variable
|
||||
if d.MinerConfig != nil {
|
||||
harmonyCfg = d.MinerConfig.HarmonyDB //copy the config to a local variable
|
||||
}
|
||||
var err error
|
||||
d.DB, err = harmonydb.NewFromConfig(harmonyCfg)
|
||||
if err == nil {
|
||||
goto yugabyteConnected
|
||||
}
|
||||
for {
|
||||
i, _, err := (&promptui.Select{
|
||||
Label: d.T("Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)"),
|
||||
Items: []string{
|
||||
d.T("Host: %s", strings.Join(harmonyCfg.Hosts, ",")),
|
||||
d.T("Port: %s", harmonyCfg.Port),
|
||||
d.T("Username: %s", harmonyCfg.Username),
|
||||
d.T("Password: %s", harmonyCfg.Password),
|
||||
d.T("Database: %s", harmonyCfg.Database),
|
||||
d.T("Continue to connect and update schema.")},
|
||||
Size: 6,
|
||||
Templates: d.selectTemplates,
|
||||
}).Run()
|
||||
if err != nil {
|
||||
d.say(notice, "Database config error occurred, abandoning migration: %s ", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
switch i {
|
||||
case 0:
|
||||
host, err := (&promptui.Prompt{
|
||||
Label: d.T("Enter the Yugabyte database host(s)"),
|
||||
}).Run()
|
||||
if err != nil {
|
||||
d.say(notice, "No host provided")
|
||||
continue
|
||||
}
|
||||
harmonyCfg.Hosts = strings.Split(host, ",")
|
||||
case 1, 2, 3, 4:
|
||||
val, err := (&promptui.Prompt{
|
||||
Label: d.T("Enter the Yugabyte database %s", []string{"port", "username", "password", "database"}[i-1]),
|
||||
}).Run()
|
||||
if err != nil {
|
||||
d.say(notice, "No value provided")
|
||||
continue
|
||||
}
|
||||
switch i {
|
||||
case 1:
|
||||
harmonyCfg.Port = val
|
||||
case 2:
|
||||
harmonyCfg.Username = val
|
||||
case 3:
|
||||
harmonyCfg.Password = val
|
||||
case 4:
|
||||
harmonyCfg.Database = val
|
||||
}
|
||||
continue
|
||||
case 5:
|
||||
d.DB, err = harmonydb.NewFromConfig(harmonyCfg)
|
||||
if err != nil {
|
||||
if err.Error() == "^C" {
|
||||
os.Exit(1)
|
||||
}
|
||||
d.say(notice, "Error connecting to Yugabyte database: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
goto yugabyteConnected
|
||||
}
|
||||
}
|
||||
|
||||
yugabyteConnected:
|
||||
d.say(plain, "Connected to Yugabyte. Schema is current.")
|
||||
if !reflect.DeepEqual(harmonyCfg, d.MinerConfig.HarmonyDB) || !d.MinerConfig.Subsystems.EnableSectorIndexDB {
|
||||
d.MinerConfig.HarmonyDB = harmonyCfg
|
||||
d.MinerConfig.Subsystems.EnableSectorIndexDB = true
|
||||
|
||||
d.say(plain, "Enabling Sector Indexing in the database.")
|
||||
buf, err := config.ConfigUpdate(d.MinerConfig, config.DefaultStorageMiner())
|
||||
if err != nil {
|
||||
d.say(notice, "Error encoding config.toml: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
_, err = (&promptui.Prompt{
|
||||
Label: d.T("Press return to update %s with Yugabyte info. A Backup file will be written to that folder before changes are made.", "config.toml")}).Run()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
p, err := homedir.Expand(d.MinerConfigPath)
|
||||
if err != nil {
|
||||
d.say(notice, "Error expanding path: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
tomlPath := path.Join(p, "config.toml")
|
||||
stat, err := os.Stat(tomlPath)
|
||||
if err != nil {
|
||||
d.say(notice, "Error reading filemode of config.toml: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fBackup, err := os.CreateTemp(p, "config-backup-*.toml")
|
||||
if err != nil {
|
||||
d.say(notice, "Error creating backup file: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fBackupContents, err := os.ReadFile(tomlPath)
|
||||
if err != nil {
|
||||
d.say(notice, "Error reading config.toml: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
_, err = fBackup.Write(fBackupContents)
|
||||
if err != nil {
|
||||
d.say(notice, "Error writing backup file: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
err = fBackup.Close()
|
||||
if err != nil {
|
||||
d.say(notice, "Error closing backup file: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
filemode := stat.Mode()
|
||||
err = os.WriteFile(path.Join(p, "config.toml"), buf, filemode)
|
||||
if err != nil {
|
||||
d.say(notice, "Error writing config.toml: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
d.say(section, "Restart Lotus Miner. ")
|
||||
}
|
||||
stepCompleted(d, d.T("Connected to Yugabyte"))
|
||||
}
|
||||
|
||||
func readMinerConfig(d *MigrationData) {
|
||||
d.say(plain, "To start, ensure your sealing pipeline is drained and shut-down lotus-miner.")
|
||||
|
||||
verifyPath := func(dir string) (*config.StorageMiner, error) {
|
||||
cfg := config.DefaultStorageMiner()
|
||||
dir, err := homedir.Expand(dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = toml.DecodeFile(path.Join(dir, "config.toml"), &cfg)
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
dirs := map[string]*config.StorageMiner{"~/.lotusminer": nil, "~/.lotus-miner-local-net": nil}
|
||||
if v := os.Getenv("LOTUS_MINER_PATH"); v != "" {
|
||||
dirs[v] = nil
|
||||
}
|
||||
for dir := range dirs {
|
||||
cfg, err := verifyPath(dir)
|
||||
if err != nil {
|
||||
delete(dirs, dir)
|
||||
}
|
||||
dirs[dir] = cfg
|
||||
}
|
||||
|
||||
var otherPath bool
|
||||
if len(dirs) > 0 {
|
||||
_, str, err := (&promptui.Select{
|
||||
Label: d.T("Select the location of your lotus-miner config directory?"),
|
||||
Items: append(lo.Keys(dirs), d.T("Other")),
|
||||
Templates: d.selectTemplates,
|
||||
}).Run()
|
||||
if err != nil {
|
||||
if err.Error() == "^C" {
|
||||
os.Exit(1)
|
||||
}
|
||||
otherPath = true
|
||||
} else {
|
||||
if str == d.T("Other") {
|
||||
otherPath = true
|
||||
} else {
|
||||
d.MinerConfigPath = str
|
||||
d.MinerConfig = dirs[str]
|
||||
}
|
||||
}
|
||||
}
|
||||
if otherPath {
|
||||
minerPathEntry:
|
||||
str, err := (&promptui.Prompt{
|
||||
Label: d.T("Enter the path to the configuration directory used by %s", "lotus-miner"),
|
||||
}).Run()
|
||||
if err != nil {
|
||||
d.say(notice, "No path provided, abandoning migration ")
|
||||
os.Exit(1)
|
||||
}
|
||||
cfg, err := verifyPath(str)
|
||||
if err != nil {
|
||||
d.say(notice, "Cannot read the config.toml file in the provided directory, Error: %s", err.Error())
|
||||
goto minerPathEntry
|
||||
}
|
||||
d.MinerConfigPath = str
|
||||
d.MinerConfig = cfg
|
||||
}
|
||||
|
||||
// Try to lock Miner repo to verify that lotus-miner is not running
|
||||
{
|
||||
r, err := repo.NewFS(d.MinerConfigPath)
|
||||
if err != nil {
|
||||
d.say(plain, "Could not create repo from directory: %s. Aborting migration", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
lr, err := r.Lock(repo.StorageMiner)
|
||||
if err != nil {
|
||||
d.say(plain, "Could not lock miner repo. Your miner must be stopped: %s\n Aborting migration", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
_ = lr.Close()
|
||||
}
|
||||
|
||||
stepCompleted(d, d.T("Read Miner Config"))
|
||||
}
|
||||
func stepCompleted(d *MigrationData, step string) {
|
||||
fmt.Print(green.Render("✔ "))
|
||||
d.say(plain, "Step Complete: %s\n", step)
|
||||
}
|
264
cmd/curio/guidedsetup/shared.go
Normal file
264
cmd/curio/guidedsetup/shared.go
Normal file
@ -0,0 +1,264 @@
|
||||
package guidedsetup
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/ipfs/go-datastore"
|
||||
"github.com/samber/lo"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
"github.com/filecoin-project/lotus/node/modules"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
)
|
||||
|
||||
const (
|
||||
FlagMinerRepo = "miner-repo"
|
||||
)
|
||||
|
||||
const FlagMinerRepoDeprecation = "storagerepo"
|
||||
|
||||
func SaveConfigToLayer(minerRepoPath, layerName string, overwrite bool, chainApiInfo string) (minerAddress address.Address, err error) {
|
||||
_, say := SetupLanguage()
|
||||
ctx := context.Background()
|
||||
|
||||
r, err := repo.NewFS(minerRepoPath)
|
||||
if err != nil {
|
||||
return minerAddress, err
|
||||
}
|
||||
|
||||
ok, err := r.Exists()
|
||||
if err != nil {
|
||||
return minerAddress, err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return minerAddress, fmt.Errorf("repo not initialized at: %s", minerRepoPath)
|
||||
}
|
||||
|
||||
lr, err := r.LockRO(repo.StorageMiner)
|
||||
if err != nil {
|
||||
return minerAddress, fmt.Errorf("locking repo: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
err = lr.Close()
|
||||
if err != nil {
|
||||
fmt.Println("error closing repo: ", err)
|
||||
}
|
||||
}()
|
||||
|
||||
cfgNode, err := lr.Config()
|
||||
if err != nil {
|
||||
return minerAddress, fmt.Errorf("getting node config: %w", err)
|
||||
}
|
||||
smCfg := cfgNode.(*config.StorageMiner)
|
||||
|
||||
db, err := harmonydb.NewFromConfig(smCfg.HarmonyDB)
|
||||
if err != nil {
|
||||
return minerAddress, fmt.Errorf("could not reach the database. Ensure the Miner config toml's HarmonyDB entry"+
|
||||
" is setup to reach Yugabyte correctly: %w", err)
|
||||
}
|
||||
|
||||
var titles []string
|
||||
err = db.Select(ctx, &titles, `SELECT title FROM harmony_config WHERE LENGTH(config) > 0`)
|
||||
if err != nil {
|
||||
return minerAddress, fmt.Errorf("miner cannot reach the db. Ensure the config toml's HarmonyDB entry"+
|
||||
" is setup to reach Yugabyte correctly: %s", err.Error())
|
||||
}
|
||||
|
||||
// Copy over identical settings:
|
||||
|
||||
buf, err := os.ReadFile(path.Join(lr.Path(), "config.toml"))
|
||||
if err != nil {
|
||||
return minerAddress, fmt.Errorf("could not read config.toml: %w", err)
|
||||
}
|
||||
curioCfg := config.DefaultCurioConfig()
|
||||
|
||||
ensureEmptyArrays(curioCfg)
|
||||
_, err = deps.LoadConfigWithUpgrades(string(buf), curioCfg)
|
||||
|
||||
if err != nil {
|
||||
return minerAddress, fmt.Errorf("could not decode toml: %w", err)
|
||||
}
|
||||
|
||||
// Populate Miner Address
|
||||
mmeta, err := lr.Datastore(ctx, "/metadata")
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("opening miner metadata datastore: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
// _ = mmeta.Close()
|
||||
}()
|
||||
|
||||
maddrBytes, err := mmeta.Get(ctx, datastore.NewKey("miner-address"))
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("getting miner address datastore entry: %w", err)
|
||||
}
|
||||
|
||||
addr, err := address.NewFromBytes(maddrBytes)
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("parsing miner actor address: %w", err)
|
||||
}
|
||||
|
||||
minerAddress = addr
|
||||
|
||||
curioCfg.Addresses = []config.CurioAddresses{{
|
||||
MinerAddresses: []string{addr.String()},
|
||||
PreCommitControl: smCfg.Addresses.PreCommitControl,
|
||||
CommitControl: smCfg.Addresses.CommitControl,
|
||||
TerminateControl: smCfg.Addresses.TerminateControl,
|
||||
DisableOwnerFallback: smCfg.Addresses.DisableOwnerFallback,
|
||||
DisableWorkerFallback: smCfg.Addresses.DisableWorkerFallback,
|
||||
}}
|
||||
|
||||
ks, err := lr.KeyStore()
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("keystore err: %w", err)
|
||||
}
|
||||
js, err := ks.Get(modules.JWTSecretName)
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("error getting JWTSecretName: %w", err)
|
||||
}
|
||||
|
||||
curioCfg.Apis.StorageRPCSecret = base64.StdEncoding.EncodeToString(js.PrivateKey)
|
||||
|
||||
curioCfg.Apis.ChainApiInfo = append(curioCfg.Apis.ChainApiInfo, chainApiInfo)
|
||||
// Express as configTOML
|
||||
configTOML := &bytes.Buffer{}
|
||||
if err = toml.NewEncoder(configTOML).Encode(curioCfg); err != nil {
|
||||
return minerAddress, err
|
||||
}
|
||||
|
||||
if lo.Contains(titles, "base") {
|
||||
// append addresses
|
||||
var baseCfg = config.DefaultCurioConfig()
|
||||
var baseText string
|
||||
err = db.QueryRow(ctx, "SELECT config FROM harmony_config WHERE title='base'").Scan(&baseText)
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("Cannot load base config: %w", err)
|
||||
}
|
||||
ensureEmptyArrays(baseCfg)
|
||||
_, err := deps.LoadConfigWithUpgrades(baseText, baseCfg)
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("Cannot load base config: %w", err)
|
||||
}
|
||||
for _, addr := range baseCfg.Addresses {
|
||||
if lo.Contains(addr.MinerAddresses, curioCfg.Addresses[0].MinerAddresses[0]) {
|
||||
goto skipWritingToBase
|
||||
}
|
||||
}
|
||||
// write to base
|
||||
{
|
||||
baseCfg.Addresses = append(baseCfg.Addresses, curioCfg.Addresses[0])
|
||||
baseCfg.Addresses = lo.Filter(baseCfg.Addresses, func(a config.CurioAddresses, _ int) bool {
|
||||
return len(a.MinerAddresses) > 0
|
||||
})
|
||||
|
||||
cb, err := config.ConfigUpdate(baseCfg, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv())
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("cannot interpret config: %w", err)
|
||||
}
|
||||
_, err = db.Exec(ctx, "UPDATE harmony_config SET config=$1 WHERE title='base'", string(cb))
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("cannot update base config: %w", err)
|
||||
}
|
||||
say(plain, "Configuration 'base' was updated to include this miner's address and its wallet setup.")
|
||||
}
|
||||
say(plain, "Compare the configurations %s to %s. Changes between the miner IDs other than wallet addreses should be a new, minimal layer for runners that need it.", "base", "mig-"+curioCfg.Addresses[0].MinerAddresses[0])
|
||||
skipWritingToBase:
|
||||
} else if layerName == "" {
|
||||
cfg, err := deps.GetDefaultConfig(true)
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("Cannot get default config: %w", err)
|
||||
}
|
||||
_, err = db.Exec(ctx, `INSERT INTO harmony_config (title, config) VALUES ('base', $1)
|
||||
ON CONFLICT(title) DO UPDATE SET config=EXCLUDED.config`, cfg)
|
||||
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("Cannot insert base config: %w", err)
|
||||
}
|
||||
say(notice, "Configuration 'base' was created to include this miner's address and its wallet setup.")
|
||||
}
|
||||
|
||||
if layerName == "" { // only make mig if base exists and we are different. // compare to base.
|
||||
layerName = fmt.Sprintf("mig-%s", curioCfg.Addresses[0].MinerAddresses[0])
|
||||
overwrite = true
|
||||
} else {
|
||||
if lo.Contains(titles, layerName) && !overwrite {
|
||||
return minerAddress, errors.New("the overwrite flag is needed to replace existing layer: " + layerName)
|
||||
}
|
||||
}
|
||||
if overwrite {
|
||||
_, err := db.Exec(ctx, "DELETE FROM harmony_config WHERE title=$1", layerName)
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("Cannot delete existing layer: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = db.Exec(ctx, "INSERT INTO harmony_config (title, config) VALUES ($1, $2)", layerName, configTOML.String())
|
||||
if err != nil {
|
||||
return minerAddress, xerrors.Errorf("Cannot insert layer after layer created message: %w", err)
|
||||
}
|
||||
say(plain, "Layer %s created. ", layerName)
|
||||
|
||||
dbSettings := getDBSettings(*smCfg)
|
||||
say(plain, "To work with the config: ")
|
||||
fmt.Println(code.Render(`curio ` + dbSettings + ` config edit base`))
|
||||
say(plain, `To run Curio: With machine or cgroup isolation, use the command (with example layer selection):`)
|
||||
fmt.Println(code.Render(`curio ` + dbSettings + ` run --layer=post`))
|
||||
return minerAddress, nil
|
||||
}
|
||||
|
||||
func getDBSettings(smCfg config.StorageMiner) string {
|
||||
dbSettings := ""
|
||||
def := config.DefaultStorageMiner().HarmonyDB
|
||||
if def.Hosts[0] != smCfg.HarmonyDB.Hosts[0] {
|
||||
dbSettings += ` --db-host="` + strings.Join(smCfg.HarmonyDB.Hosts, ",") + `"`
|
||||
}
|
||||
if def.Port != smCfg.HarmonyDB.Port {
|
||||
dbSettings += " --db-port=" + smCfg.HarmonyDB.Port
|
||||
}
|
||||
if def.Username != smCfg.HarmonyDB.Username {
|
||||
dbSettings += ` --db-user="` + smCfg.HarmonyDB.Username + `"`
|
||||
}
|
||||
if def.Password != smCfg.HarmonyDB.Password {
|
||||
dbSettings += ` --db-password="` + smCfg.HarmonyDB.Password + `"`
|
||||
}
|
||||
if def.Database != smCfg.HarmonyDB.Database {
|
||||
dbSettings += ` --db-name="` + smCfg.HarmonyDB.Database + `"`
|
||||
}
|
||||
return dbSettings
|
||||
}
|
||||
|
||||
func ensureEmptyArrays(cfg *config.CurioConfig) {
|
||||
if cfg.Addresses == nil {
|
||||
cfg.Addresses = []config.CurioAddresses{}
|
||||
} else {
|
||||
for i := range cfg.Addresses {
|
||||
if cfg.Addresses[i].PreCommitControl == nil {
|
||||
cfg.Addresses[i].PreCommitControl = []string{}
|
||||
}
|
||||
if cfg.Addresses[i].CommitControl == nil {
|
||||
cfg.Addresses[i].CommitControl = []string{}
|
||||
}
|
||||
if cfg.Addresses[i].TerminateControl == nil {
|
||||
cfg.Addresses[i].TerminateControl = []string{}
|
||||
}
|
||||
}
|
||||
}
|
||||
if cfg.Apis.ChainApiInfo == nil {
|
||||
cfg.Apis.ChainApiInfo = []string{}
|
||||
}
|
||||
}
|
331
cmd/curio/internal/translations/catalog.go
Normal file
331
cmd/curio/internal/translations/catalog.go
Normal file
@ -0,0 +1,331 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package translations
|
||||
|
||||
import (
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
"golang.org/x/text/message/catalog"
|
||||
)
|
||||
|
||||
type dictionary struct {
|
||||
index []uint32
|
||||
data string
|
||||
}
|
||||
|
||||
func (d *dictionary) Lookup(key string) (data string, ok bool) {
|
||||
p, ok := messageKeyToIndex[key]
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
start, end := d.index[p], d.index[p+1]
|
||||
if start == end {
|
||||
return "", false
|
||||
}
|
||||
return d.data[start:end], true
|
||||
}
|
||||
|
||||
func init() {
|
||||
dict := map[string]catalog.Dictionary{
|
||||
"en": &dictionary{index: enIndex, data: enData},
|
||||
"ko": &dictionary{index: koIndex, data: koData},
|
||||
"zh": &dictionary{index: zhIndex, data: zhData},
|
||||
}
|
||||
fallback := language.MustParse("en")
|
||||
cat, err := catalog.NewFromMap(dict, catalog.Fallback(fallback))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
message.DefaultCatalog = cat
|
||||
}
|
||||
|
||||
var messageKeyToIndex = map[string]int{
|
||||
"Aborting migration.": 41,
|
||||
"Aborting remaining steps.": 19,
|
||||
"Aggregate-Anonymous: version, net, and Miner power (bucketed).": 16,
|
||||
"Cannot read the config.toml file in the provided directory, Error: %s": 70,
|
||||
"Compare the configurations %s to %s. Changes between the miner IDs other than wallet addreses should be a new, minimal layer for runners that need it.": 76,
|
||||
"Configuration 'base' was created to include this miner's address and its wallet setup.": 77,
|
||||
"Configuration 'base' was updated to include this miner's address and its wallet setup.": 75,
|
||||
"Connected to Yugabyte": 64,
|
||||
"Connected to Yugabyte. Schema is current.": 56,
|
||||
"Continue to connect and update schema.": 49,
|
||||
"Could not create repo from directory: %s. Aborting migration": 71,
|
||||
"Could not lock miner repo. Your miner must be stopped: %s\n Aborting migration": 72,
|
||||
"Ctrl+C pressed in Terminal": 3,
|
||||
"Database config error occurred, abandoning migration: %s ": 50,
|
||||
"Database: %s": 48,
|
||||
"Documentation: ": 27,
|
||||
"Each step needs your confirmation and can be reversed. Press Ctrl+C to exit at any time.": 1,
|
||||
"Enabling Sector Indexing in the database.": 57,
|
||||
"Enter the Yugabyte database %s": 53,
|
||||
"Enter the Yugabyte database host(s)": 51,
|
||||
"Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)": 43,
|
||||
"Enter the path to the configuration directory used by %s": 68,
|
||||
"Error connecting to Yugabyte database: %s": 55,
|
||||
"Error connecting to lotus node: %s %s": 9,
|
||||
"Error encoding config.toml: %s": 58,
|
||||
"Error expanding path: %s": 60,
|
||||
"Error getting miner info: %s": 22,
|
||||
"Error getting miner power: %s": 20,
|
||||
"Error getting token: %s": 11,
|
||||
"Error interpreting miner ID: %s: ID: %s": 36,
|
||||
"Error marshalling message: %s": 21,
|
||||
"Error reading filemode of config.toml: %s": 61,
|
||||
"Error reading from database: %s. Aborting Migration.": 8,
|
||||
"Error saving config to layer: %s. Aborting Migration": 12,
|
||||
"Error sending message: %s": 24,
|
||||
"Error sending message: Status %s, Message: ": 25,
|
||||
"Error signing message: %s": 23,
|
||||
"Error verifying sectors: %s": 37,
|
||||
"Error writing config.toml: %s": 62,
|
||||
"Filecoin %s channels: %s and %s": 30,
|
||||
"Hint: I am someone running Curio on net.": 17,
|
||||
"Host: %s": 44,
|
||||
"Individual Data: Miner ID, Curio version, net (%s or %s). Signed.": 15,
|
||||
"Layer %s created. ": 78,
|
||||
"Lotus-Miner to Curio Migration.": 4,
|
||||
"Message sent.": 26,
|
||||
"Migrating config.toml to database.": 7,
|
||||
"No host provided": 52,
|
||||
"No path provided, abandoning migration ": 69,
|
||||
"No value provided": 54,
|
||||
"Nothing.": 18,
|
||||
"Now shut down lotus-miner and move the systems to %s.": 39,
|
||||
"One database can serve multiple miner IDs: Run a migration for each lotus-miner.": 33,
|
||||
"Other": 67,
|
||||
"Password: %s": 47,
|
||||
"Please start (or restart) %s now that database credentials are in %s.": 34,
|
||||
"Point your browser to your web GUI to complete setup with %s and advanced featues.": 32,
|
||||
"Port: %s": 45,
|
||||
"Press return to continue": 40,
|
||||
"Press return to update %s with Yugabyte info. Backup the file now.": 59,
|
||||
"Protocol Labs wants to improve the software you use. Tell the team you're using Curio.": 13,
|
||||
"Read Miner Config": 73,
|
||||
"Restart Lotus Miner. ": 63,
|
||||
"Sectors verified. %d sector locations found.": 42,
|
||||
"Select the location of your lotus-miner config directory?": 66,
|
||||
"Select what you want to share with the Curio team.": 14,
|
||||
"Start multiple Curio instances with the '%s' layer to redundancy.": 31,
|
||||
"Step Complete: %s\n": 74,
|
||||
"The '%s' layer stores common configuration. All curio instances can include it in their %s argument.": 28,
|
||||
"The sectors are in the database. The database is ready for %s.": 38,
|
||||
"This interactive tool migrates lotus-miner to Curio in 5 minutes.": 0,
|
||||
"To run Curio: With machine or cgroup isolation, use the command (with example layer selection):": 80,
|
||||
"To start, ensure your sealing pipeline is drained and shut-down lotus-miner.": 65,
|
||||
"To work with the config: ": 79,
|
||||
"Try the web interface with %s for further guided improvements.": 5,
|
||||
"Use the arrow keys to navigate: ↓ ↑ → ← ": 2,
|
||||
"Username: %s": 46,
|
||||
"Waiting for %s to write sectors into Yugabyte.": 35,
|
||||
"You can add other layers for per-machine configuration changes.": 29,
|
||||
"You can now migrate your market node (%s), if applicable.": 6,
|
||||
"could not get API info for FullNode: %w": 10,
|
||||
}
|
||||
|
||||
var enIndex = []uint32{ // 82 elements
|
||||
// Entry 0 - 1F
|
||||
0x00000000, 0x00000042, 0x0000009b, 0x000000d0,
|
||||
0x000000eb, 0x0000010b, 0x0000014d, 0x0000018a,
|
||||
0x000001ad, 0x000001e5, 0x00000211, 0x0000023c,
|
||||
0x00000257, 0x0000028f, 0x000002e6, 0x00000319,
|
||||
0x00000361, 0x000003a0, 0x000003c9, 0x000003d2,
|
||||
0x000003ec, 0x0000040d, 0x0000042e, 0x0000044e,
|
||||
0x0000046b, 0x00000488, 0x000004bb, 0x000004c9,
|
||||
0x000004dd, 0x00000548, 0x00000588, 0x000005b1,
|
||||
// Entry 20 - 3F
|
||||
0x000005f6, 0x0000064c, 0x0000069d, 0x000006e9,
|
||||
0x0000071b, 0x00000749, 0x00000768, 0x000007aa,
|
||||
0x000007e3, 0x000007fc, 0x00000810, 0x00000840,
|
||||
0x000008a2, 0x000008ae, 0x000008ba, 0x000008ca,
|
||||
0x000008da, 0x000008ea, 0x00000911, 0x00000952,
|
||||
0x00000976, 0x00000987, 0x000009a9, 0x000009bb,
|
||||
0x000009e8, 0x00000a12, 0x00000a3c, 0x00000a5e,
|
||||
0x00000aa4, 0x00000ac0, 0x00000aed, 0x00000b0e,
|
||||
// Entry 40 - 5F
|
||||
0x00000b28, 0x00000b3e, 0x00000b8b, 0x00000bc5,
|
||||
0x00000bcb, 0x00000c07, 0x00000c33, 0x00000c7c,
|
||||
0x00000cbc, 0x00000d0d, 0x00000d1f, 0x00000d39,
|
||||
0x00000d90, 0x00000e2d, 0x00000e84, 0x00000e9e,
|
||||
0x00000ebc, 0x00000f1c,
|
||||
} // Size: 352 bytes
|
||||
|
||||
const enData string = "" + // Size: 3868 bytes
|
||||
"\x02This interactive tool migrates lotus-miner to Curio in 5 minutes." +
|
||||
"\x02Each step needs your confirmation and can be reversed. Press Ctrl+C " +
|
||||
"to exit at any time.\x04\x00\x01 0\x02Use the arrow keys to navigate: ↓ " +
|
||||
"↑ → ←\x02Ctrl+C pressed in Terminal\x02Lotus-Miner to Curio Migration." +
|
||||
"\x02Try the web interface with %[1]s for further guided improvements." +
|
||||
"\x02You can now migrate your market node (%[1]s), if applicable.\x02Migr" +
|
||||
"ating config.toml to database.\x02Error reading from database: %[1]s. Ab" +
|
||||
"orting Migration.\x02Error connecting to lotus node: %[1]s %[2]s\x02coul" +
|
||||
"d not get API info for FullNode: %[1]w\x02Error getting token: %[1]s\x02" +
|
||||
"Error saving config to layer: %[1]s. Aborting Migration\x02Protocol Labs" +
|
||||
" wants to improve the software you use. Tell the team you're using Curio" +
|
||||
".\x02Select what you want to share with the Curio team.\x02Individual Da" +
|
||||
"ta: Miner ID, Curio version, net (%[1]s or %[2]s). Signed.\x02Aggregate-" +
|
||||
"Anonymous: version, net, and Miner power (bucketed).\x02Hint: I am someo" +
|
||||
"ne running Curio on net.\x02Nothing.\x02Aborting remaining steps.\x02Err" +
|
||||
"or getting miner power: %[1]s\x02Error marshalling message: %[1]s\x02Err" +
|
||||
"or getting miner info: %[1]s\x02Error signing message: %[1]s\x02Error se" +
|
||||
"nding message: %[1]s\x04\x00\x01 .\x02Error sending message: Status %[1]" +
|
||||
"s, Message:\x02Message sent.\x04\x00\x01 \x0f\x02Documentation:\x02The '" +
|
||||
"%[1]s' layer stores common configuration. All curio instances can includ" +
|
||||
"e it in their %[2]s argument.\x02You can add other layers for per-machin" +
|
||||
"e configuration changes.\x02Filecoin %[1]s channels: %[2]s and %[3]s\x02" +
|
||||
"Start multiple Curio instances with the '%[1]s' layer to redundancy.\x02" +
|
||||
"Point your browser to your web GUI to complete setup with %[1]s and adva" +
|
||||
"nced featues.\x02One database can serve multiple miner IDs: Run a migrat" +
|
||||
"ion for each lotus-miner.\x02Please start (or restart) %[1]s now that da" +
|
||||
"tabase credentials are in %[2]s.\x02Waiting for %[1]s to write sectors i" +
|
||||
"nto Yugabyte.\x02Error interpreting miner ID: %[1]s: ID: %[2]s\x02Error " +
|
||||
"verifying sectors: %[1]s\x02The sectors are in the database. The databas" +
|
||||
"e is ready for %[1]s.\x02Now shut down lotus-miner and move the systems " +
|
||||
"to %[1]s.\x02Press return to continue\x02Aborting migration.\x02Sectors " +
|
||||
"verified. %[1]d sector locations found.\x02Enter the info to connect to " +
|
||||
"your Yugabyte database installation (https://download.yugabyte.com/)\x02" +
|
||||
"Host: %[1]s\x02Port: %[1]s\x02Username: %[1]s\x02Password: %[1]s\x02Data" +
|
||||
"base: %[1]s\x02Continue to connect and update schema.\x04\x00\x01 <\x02D" +
|
||||
"atabase config error occurred, abandoning migration: %[1]s\x02Enter the " +
|
||||
"Yugabyte database host(s)\x02No host provided\x02Enter the Yugabyte data" +
|
||||
"base %[1]s\x02No value provided\x02Error connecting to Yugabyte database" +
|
||||
": %[1]s\x02Connected to Yugabyte. Schema is current.\x02Enabling Sector " +
|
||||
"Indexing in the database.\x02Error encoding config.toml: %[1]s\x02Press " +
|
||||
"return to update %[1]s with Yugabyte info. Backup the file now.\x02Error" +
|
||||
" expanding path: %[1]s\x02Error reading filemode of config.toml: %[1]s" +
|
||||
"\x02Error writing config.toml: %[1]s\x04\x00\x01 \x15\x02Restart Lotus M" +
|
||||
"iner.\x02Connected to Yugabyte\x02To start, ensure your sealing pipeline" +
|
||||
" is drained and shut-down lotus-miner.\x02Select the location of your lo" +
|
||||
"tus-miner config directory?\x02Other\x02Enter the path to the configurat" +
|
||||
"ion directory used by %[1]s\x04\x00\x01 '\x02No path provided, abandonin" +
|
||||
"g migration\x02Cannot read the config.toml file in the provided director" +
|
||||
"y, Error: %[1]s\x02Could not create repo from directory: %[1]s. Aborting" +
|
||||
" migration\x02Could not lock miner repo. Your miner must be stopped: %[1" +
|
||||
"]s\x0a Aborting migration\x02Read Miner Config\x04\x00\x01\x0a\x15\x02St" +
|
||||
"ep Complete: %[1]s\x02Configuration 'base' was updated to include this m" +
|
||||
"iner's address and its wallet setup.\x02Compare the configurations %[1]s" +
|
||||
" to %[2]s. Changes between the miner IDs other than wallet addreses shou" +
|
||||
"ld be a new, minimal layer for runners that need it.\x02Configuration 'b" +
|
||||
"ase' was created to include this miner's address and its wallet setup." +
|
||||
"\x04\x00\x01 \x15\x02Layer %[1]s created.\x04\x00\x01 \x19\x02To work wi" +
|
||||
"th the config:\x02To run Curio: With machine or cgroup isolation, use th" +
|
||||
"e command (with example layer selection):"
|
||||
|
||||
var koIndex = []uint32{ // 82 elements
|
||||
// Entry 0 - 1F
|
||||
0x00000000, 0x0000004d, 0x000000c8, 0x0000010c,
|
||||
0x0000012d, 0x00000150, 0x00000150, 0x000001a0,
|
||||
0x000001da, 0x0000022f, 0x0000022f, 0x0000022f,
|
||||
0x0000022f, 0x00000287, 0x00000315, 0x0000034e,
|
||||
0x000003aa, 0x000003f4, 0x00000437, 0x00000452,
|
||||
0x00000477, 0x000004b1, 0x000004e4, 0x0000051e,
|
||||
0x00000548, 0x00000572, 0x000005b4, 0x000005d8,
|
||||
0x000005e5, 0x0000066b, 0x000006bd, 0x000006bd,
|
||||
// Entry 20 - 3F
|
||||
0x000006bd, 0x0000071e, 0x0000071e, 0x0000071e,
|
||||
0x00000762, 0x00000762, 0x00000789, 0x000007f4,
|
||||
0x0000083e, 0x00000865, 0x00000880, 0x000008cf,
|
||||
0x0000093d, 0x0000094e, 0x0000095c, 0x00000974,
|
||||
0x00000988, 0x000009a2, 0x000009cc, 0x00000a2f,
|
||||
0x00000a6b, 0x00000a95, 0x00000acd, 0x00000af1,
|
||||
0x00000b45, 0x00000b86, 0x00000b86, 0x00000bcd,
|
||||
0x00000c39, 0x00000c39, 0x00000c88, 0x00000cc6,
|
||||
// Entry 40 - 5F
|
||||
0x00000cea, 0x00000d00, 0x00000d6b, 0x00000dba,
|
||||
0x00000dc1, 0x00000e09, 0x00000e5b, 0x00000eb5,
|
||||
0x00000eb5, 0x00000eb5, 0x00000ecd, 0x00000ee7,
|
||||
0x00000f51, 0x0000100b, 0x0000106f, 0x0000109e,
|
||||
0x0000109e, 0x0000112a,
|
||||
} // Size: 352 bytes
|
||||
|
||||
const koData string = "" + // Size: 4394 bytes
|
||||
"\x02이 대화형 도구는 5분 안에 lotus-miner를 Curio로 이주합니다.\x02각 단계는 확인이 필요하며 되돌릴 수 있" +
|
||||
"습니다. 언제든지 Ctrl+C를 눌러 종료할 수 있습니다.\x04\x00\x01 ?\x02화살표 키를 사용하여 이동하세요: ↓" +
|
||||
" ↑ → ←\x02터미널에서 Ctrl+C가 눌림\x02Lotus-Miner에서 Curio로 이주.\x02해당하는 경우 이제 시장 " +
|
||||
"노드를 이주할 수 있습니다 (%[1]s).\x02config.toml을 데이터베이스로 이주 중입니다.\x02데이터베이스에서 읽" +
|
||||
"는 중 오류 발생: %[1]s. 마이그레이션 중단.\x02레이어에 구성을 저장하는 중 오류 발생: %[1]s. 마이그레이션 중" +
|
||||
"단\x02Protocol Labs는 당신이 사용하는 소프트웨어를 개선하고 싶어합니다. Curio를 사용 중이라고 팀에 알려주세" +
|
||||
"요.\x02Curio 팀과 공유하고 싶은 것을 선택하세요.\x02개별 데이터: 마이너 ID, Curio 버전, 네트워크 (%[" +
|
||||
"1]s 또는 %[2]s). 서명됨.\x02집계-익명: 버전, 네트워크, 그리고 마이너 파워 (버킷).\x02힌트: 네트워크에서 C" +
|
||||
"urio를 실행 중인 사람입니다.\x02아무것도 없습니다.\x02나머지 단계를 중단합니다.\x02마이너 파워를 가져오는 중 오류 " +
|
||||
"발생: %[1]s\x02메시지를 마샬하는 중 오류 발생: %[1]s\x02마이너 정보를 가져오는 중 오류 발생: %[1]s" +
|
||||
"\x02메시지 서명 중 오류 발생: %[1]s\x02메시지 전송 중 오류 발생: %[1]s\x04\x00\x01 =\x02메시지 " +
|
||||
"전송 중 오류 발생: 상태 %[1]s, 메시지:\x02메시지가 전송되었습니다.\x04\x00\x01 \x08\x02문서:" +
|
||||
"\x02'%[1]s' 레이어에는 공통 구성이 저장됩니다. 모든 Curio 인스턴스는 %[2]s 인수에 포함시킬 수 있습니다." +
|
||||
"\x02기계별 구성 변경을 위해 다른 레이어를 추가할 수 있습니다.\x02브라우저를 웹 GUI로 이동하여 %[1]s 및 고급 기능" +
|
||||
"으로 설정을 완료하세요.\x02%[1]s가 Yugabyte에 섹터를 기록하도록 대기 중입니다.\x02섹터 확인 중 오류 발생:" +
|
||||
" %[1]s\x02섹터가 데이터베이스에 있습니다. 데이터베이스가 %[1]s를 위해 준비되었습니다.\x02이제 lotus-miner" +
|
||||
"를 종료하고 시스템을 %[1]s로 이동하세요.\x02계속하려면 리턴을 누르세요\x02마이그레이션 중단.\x02섹터가 확인되었습" +
|
||||
"니다. %[1]d개의 섹터 위치를 찾았습니다.\x02Yugabyte 데이터베이스 설치에 연결할 정보를 입력하십시오 (https" +
|
||||
"://download.yugabyte.com/)\x02호스트: %[1]s\x02포트: %[1]s\x02사용자 이름: %[1]s" +
|
||||
"\x02비밀번호: %[1]s\x02데이터베이스: %[1]s\x02계속 연결 및 스키마 업데이트.\x04\x00\x01 ^\x02데" +
|
||||
"이터베이스 구성 오류가 발생하여 마이그레이션을 포기합니다: %[1]s\x02Yugabyte 데이터베이스 호스트를 입력하십시오" +
|
||||
"\x02호스트가 제공되지 않았습니다\x02Yugabyte 데이터베이스 %[1]s을 입력하십시오\x02값이 제공되지 않았습니다" +
|
||||
"\x02Yugabyte 데이터베이스에 연결하는 중 오류가 발생했습니다: %[1]s\x02Yugabyte에 연결되었습니다. 스키마가" +
|
||||
" 현재입니다.\x02config.toml을 인코딩하는 중 오류가 발생했습니다: %[1]s\x02%[1]s을 Yugabyte 정보로" +
|
||||
" 업데이트하려면 리턴을 누르세요. 지금 파일을 백업하세요.\x02config.toml의 파일 모드를 읽는 중 오류가 발생했습니다:" +
|
||||
" %[1]s\x02config.toml을 쓰는 중 오류가 발생했습니다: %[1]s\x04\x00\x01 \x1f\x02로터스 마이" +
|
||||
"너 재시작.\x02Yugabyte에 연결됨\x02시작하려면 밀봉 파이프라인이 비어 있고 lotus-miner가 종료되었는지 확" +
|
||||
"인하세요.\x02로터스 마이너 구성 디렉토리의 위치를 선택하시겠습니까?\x02기타\x02%[1]s에서 사용하는 구성 디렉터리 " +
|
||||
"경로를 입력하세요.\x04\x00\x01 M\x02경로가 제공되지 않았으므로 마이그레이션을 포기합니다\x02제공된 디렉토리에서" +
|
||||
" config.toml 파일을 읽을 수 없습니다. 오류: %[1]s\x02마이너 구성 읽기\x04\x00\x01\x0a\x15" +
|
||||
"\x02단계 완료: %[1]s\x02이 마이너의 주소와 지갑 설정을 포함하도록 구성 'base'가 업데이트되었습니다.\x02구성 " +
|
||||
"%[1]s를 %[2]s과 비교하세요. 지갑 주소 이외의 마이너 ID 사이의 변경 사항은 필요한 실행자를 위한 새로운 최소한의 레이" +
|
||||
"어여야 합니다.\x02이 마이너의 주소와 지갑 설정을 포함하도록 구성 'base'가 생성되었습니다.\x04\x00\x01 *" +
|
||||
"\x02레이어 %[1]s가 생성되었습니다.\x02Curio를 실행하려면: 기계 또는 cgroup 격리를 사용하여 다음 명령을 사용" +
|
||||
"하세요 (예제 레이어 선택과 함께):"
|
||||
|
||||
var zhIndex = []uint32{ // 82 elements
|
||||
// Entry 0 - 1F
|
||||
0x00000000, 0x00000048, 0x00000097, 0x000000ca,
|
||||
0x000000e3, 0x00000100, 0x00000100, 0x00000141,
|
||||
0x0000016b, 0x000001a4, 0x000001a4, 0x000001a4,
|
||||
0x000001a4, 0x000001dd, 0x0000022f, 0x0000025c,
|
||||
0x000002a9, 0x000002e7, 0x00000317, 0x00000321,
|
||||
0x00000337, 0x0000035b, 0x00000379, 0x0000039d,
|
||||
0x000003bb, 0x000003d9, 0x0000040e, 0x00000421,
|
||||
0x00000430, 0x0000048a, 0x000004c7, 0x000004c7,
|
||||
// Entry 20 - 3F
|
||||
0x000004c7, 0x0000051e, 0x0000051e, 0x0000051e,
|
||||
0x00000544, 0x00000544, 0x00000562, 0x0000059e,
|
||||
0x000005d0, 0x000005e0, 0x000005f0, 0x00000623,
|
||||
0x0000067d, 0x0000068c, 0x0000069b, 0x000006ad,
|
||||
0x000006bc, 0x000006ce, 0x000006ed, 0x00000725,
|
||||
0x0000074a, 0x0000075a, 0x00000778, 0x00000785,
|
||||
0x000007b1, 0x000007de, 0x000007de, 0x00000801,
|
||||
0x00000845, 0x00000845, 0x00000874, 0x00000897,
|
||||
// Entry 40 - 5F
|
||||
0x000008b7, 0x000008cc, 0x00000917, 0x00000947,
|
||||
0x0000094e, 0x00000978, 0x0000099c, 0x000009e0,
|
||||
0x000009e0, 0x000009e0, 0x000009f3, 0x00000a0d,
|
||||
0x00000a59, 0x00000adb, 0x00000b27, 0x00000b41,
|
||||
0x00000b41, 0x00000b98,
|
||||
} // Size: 352 bytes
|
||||
|
||||
const zhData string = "" + // Size: 2968 bytes
|
||||
"\x02这个交互式工具可以在5分钟内将lotus-miner迁移到Curio。\x02每一步都需要您的确认,并且可以撤销。随时按Ctrl+C退出" +
|
||||
"。\x04\x00\x01 .\x02使用箭头键进行导航:↓ ↑ → ←\x02在终端中按下Ctrl+C\x02Lotus-Miner到Cu" +
|
||||
"rio迁移。\x02如果适用,您现在可以迁移您的市场节点(%[1]s)。\x02正在将config.toml迁移到数据库。\x02读取数据库时出" +
|
||||
"错:%[1]s。正在中止迁移。\x02保存配置到层时出错:%[1]s。正在中止迁移\x02Protocol Labs希望改进您使用的软件。告" +
|
||||
"诉团队您正在使用Curio。\x02选择您想与Curio团队分享的内容。\x02个人数据:矿工ID、Curio版本、网络(%[1]s或%[2" +
|
||||
"]s)。已签名。\x02聚合-匿名:版本、网络和矿工功率(分桶)。\x02提示:我是在网络上运行Curio的人。\x02没有。\x02中止剩余步" +
|
||||
"骤。\x02获取矿工功率时出错:%[1]s\x02整理消息时出错:%[1]s\x02获取矿工信息时出错:%[1]s\x02签署消息时出错:%" +
|
||||
"[1]s\x02发送消息时出错:%[1]s\x04\x00\x01 0\x02发送消息时出错:状态%[1]s,消息:\x02消息已发送。\x04" +
|
||||
"\x00\x01 \x0a\x02文档:\x02'%[1]s'层存储通用配置。所有Curio实例都可以在其%[2]s参数中包含它。\x02您可以" +
|
||||
"添加其他层进行每台机器的配置更改。\x02将您的浏览器指向您的网络GUI,以使用%[1]s和高级功能完成设置。\x02等待%[1]s将扇区写" +
|
||||
"入Yugabyte。\x02验证扇区时出错:%[1]s\x02扇区在数据库中。数据库已准备好用于%[1]s。\x02现在关闭lotus-mi" +
|
||||
"ner并将系统移至%[1]s。\x02按回车继续\x02中止迁移。\x02扇区已验证。发现了%[1]d个扇区位置。\x02输入连接到您的Yuga" +
|
||||
"byte数据库安装的信息(https://download.yugabyte.com/)\x02主机:%[1]s\x02端口:%[1]s\x02" +
|
||||
"用户名:%[1]s\x02密码:%[1]s\x02数据库:%[1]s\x02继续连接和更新架构。\x04\x00\x01 3\x02发生数据" +
|
||||
"库配置错误,放弃迁移:%[1]s\x02输入Yugabyte数据库主机(S)\x02未提供主机\x02输入Yugabyte数据库 %[1]s" +
|
||||
"\x02未提供值\x02连接到Yugabyte数据库时出错:%[1]s\x02已连接到Yugabyte。模式是当前的。\x02编码config." +
|
||||
"toml时出错:%[1]s\x02按回车更新%[1]s以获取Yugabyte信息。现在备份文件。\x02读取config.toml文件模式时出错" +
|
||||
":%[1]s\x02写入config.toml时出错:%[1]s\x04\x00\x01 \x1b\x02重新启动Lotus Miner。" +
|
||||
"\x02已连接到Yugabyte\x02开始之前,请确保您的密封管道已排空并关闭lotus-miner。\x02选择您的lotus-miner配" +
|
||||
"置目录的位置?\x02其他\x02输入%[1]s使用的配置目录的路径\x04\x00\x01 \x1f\x02未提供路径,放弃迁移\x02无" +
|
||||
"法读取提供的目录中的config.toml文件,错误:%[1]s\x02读取矿工配置\x04\x00\x01\x0a\x15\x02步骤完成" +
|
||||
":%[1]s\x02配置'base'已更新,包含了这个矿工的地址和其钱包设置。\x02比较配置%[1]s和%[2]s。矿工ID之间除了钱包地" +
|
||||
"址的变化应该是需要的运行者的一个新的、最小的层。\x02配置'base'已创建,包括了这个矿工的地址和其钱包设置。\x04\x00\x01 " +
|
||||
"\x15\x02层%[1]s已创建。\x02运行Curio:使用机器或cgroup隔离,使用命令(附带示例层选择):"
|
||||
|
||||
// Total table size 12286 bytes (11KiB); checksum: 15B16994
|
82
cmd/curio/internal/translations/knowns/main.go
Normal file
82
cmd/curio/internal/translations/knowns/main.go
Normal file
@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
for _, arg := range os.Args {
|
||||
handleKnowns(arg)
|
||||
}
|
||||
}
|
||||
|
||||
func handleKnowns(pathStart string) {
|
||||
outpath := path.Join(pathStart, "out.gotext.json")
|
||||
b, err := os.ReadFile(outpath)
|
||||
if err != nil {
|
||||
fmt.Println("cannot open "+outpath+":", err)
|
||||
return
|
||||
}
|
||||
type TMsg struct {
|
||||
ID string `json:"id"`
|
||||
Translation string `json:"translation"`
|
||||
Message string `json:"message"`
|
||||
Placeholder json.RawMessage `json:"placeholder"`
|
||||
}
|
||||
type Dataformat struct {
|
||||
Language string `json:"language"`
|
||||
Messages []TMsg `json:"messages"`
|
||||
}
|
||||
var outData Dataformat
|
||||
err = json.NewDecoder(bytes.NewBuffer(b)).Decode(&outData)
|
||||
if err != nil {
|
||||
fmt.Println("cannot decode "+outpath+":", err)
|
||||
return
|
||||
}
|
||||
|
||||
f, err := os.Open(path.Join(pathStart, "messages.gotext.json"))
|
||||
if err != nil {
|
||||
fmt.Println("cannot open "+path.Join(pathStart, "messages.gotext.json")+":", err)
|
||||
return
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
var msgData Dataformat
|
||||
err = json.NewDecoder(f).Decode(&msgData)
|
||||
if err != nil {
|
||||
fmt.Println("cannot decode "+path.Join(pathStart, "messages.gotext.json")+":", err)
|
||||
return
|
||||
}
|
||||
|
||||
knowns := map[string]string{}
|
||||
for _, msg := range msgData.Messages {
|
||||
knowns[msg.ID] = msg.Translation
|
||||
}
|
||||
|
||||
toTranslate := lo.Filter(outData.Messages, func(msg TMsg, _ int) bool {
|
||||
_, ok := knowns[msg.ID]
|
||||
return !ok
|
||||
})
|
||||
|
||||
outData.Messages = toTranslate // drop the "done" messages
|
||||
var outJSON bytes.Buffer
|
||||
enc := json.NewEncoder(&outJSON)
|
||||
enc.SetIndent(" ", " ")
|
||||
err = enc.Encode(outData)
|
||||
if err != nil {
|
||||
fmt.Println("cannot encode "+outpath+":", err)
|
||||
return
|
||||
}
|
||||
err = os.WriteFile(outpath, outJSON.Bytes(), 0644)
|
||||
if err != nil {
|
||||
fmt.Println("cannot write "+outpath+":", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("rearranged successfully")
|
||||
}
|
1104
cmd/curio/internal/translations/locales/en/out.gotext.json
Normal file
1104
cmd/curio/internal/translations/locales/en/out.gotext.json
Normal file
File diff suppressed because it is too large
Load Diff
704
cmd/curio/internal/translations/locales/ko/messages.gotext.json
Normal file
704
cmd/curio/internal/translations/locales/ko/messages.gotext.json
Normal file
@ -0,0 +1,704 @@
|
||||
{
|
||||
"language": "ko",
|
||||
"messages": [
|
||||
{
|
||||
"id": "This interactive tool will walk you through migration of Curio.\nPress Ctrl+C to exit at any time.",
|
||||
"message": "This interactive tool will walk you through migration of Curio.\nPress Ctrl+C to exit at any time.",
|
||||
"translation": "이 대화형 도구는 Curio 마이그레이션 과정을 안내합니다.\n언제든지 종료하려면 Ctrl+C를 누르십시오."
|
||||
},
|
||||
{
|
||||
"id": "This tool confirms each action it does.",
|
||||
"message": "This tool confirms each action it does.",
|
||||
"translation": "이 도구는 수행하는 각 작업을 확인합니다."
|
||||
},
|
||||
{
|
||||
"id": "Ctrl+C pressed in Terminal",
|
||||
"message": "Ctrl+C pressed in Terminal",
|
||||
"translation": "터미널에서 Ctrl+C가 눌림"
|
||||
},
|
||||
{
|
||||
"id": "Verifying Sectors exist in Yugabyte.",
|
||||
"message": "Verifying Sectors exist in Yugabyte.",
|
||||
"translation": "Yugabyte에 섹터가 존재하는지 확인 중."
|
||||
},
|
||||
{
|
||||
"id": "Error verifying sectors: {Error}",
|
||||
"message": "Error verifying sectors: {Error}",
|
||||
"translation": "섹터 확인 중 오류 발생: {Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Sectors verified. {I} sectors found.",
|
||||
"message": "Sectors verified. {I} sectors found.",
|
||||
"translation": "섹터가 확인되었습니다. {I}개의 섹터가 발견되었습니다.",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "I",
|
||||
"string": "%[1]d",
|
||||
"type": "[]int",
|
||||
"underlyingType": "[]int",
|
||||
"argNum": 1,
|
||||
"expr": "i"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Never remove the database info from the config.toml for lotus-miner as it avoids double PoSt.",
|
||||
"message": "Never remove the database info from the config.toml for lotus-miner as it avoids double PoSt.",
|
||||
"translation": "로터스 마이너의 config.toml에서 데이터베이스 정보를 제거하지 마십시오. 두 번의 PoSt를 피하기 위함입니다."
|
||||
},
|
||||
{
|
||||
"id": "Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)",
|
||||
"message": "Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)",
|
||||
"translation": "Yugabyte 데이터베이스 설치에 연결할 정보를 입력하십시오 (https://download.yugabyte.com/)"
|
||||
},
|
||||
{
|
||||
"id": "Host: {Hosts_}",
|
||||
"message": "Host: {Hosts_}",
|
||||
"translation": "호스트: {Hosts_}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Hosts_",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "strings.Join(harmonycfg.Hosts, \",\")"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Port: {Port}",
|
||||
"message": "Port: {Port}",
|
||||
"translation": "포트: {Port}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Port",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "harmonycfg.Port"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Username: {Username}",
|
||||
"message": "Username: {Username}",
|
||||
"translation": "사용자 이름: {Username}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Username",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "harmonycfg.Username"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Password: {Password}",
|
||||
"message": "Password: {Password}",
|
||||
"translation": "비밀번호: {Password}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Password",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "harmonycfg.Password"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Database: {Database}",
|
||||
"message": "Database: {Database}",
|
||||
"translation": "데이터베이스: {Database}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Database",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "harmonycfg.Database"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Continue to connect and update schema.",
|
||||
"message": "Continue to connect and update schema.",
|
||||
"translation": "계속 연결 및 스키마 업데이트."
|
||||
},
|
||||
{
|
||||
"id": "Database config error occurred, abandoning migration: {Error}",
|
||||
"message": "Database config error occurred, abandoning migration: {Error}",
|
||||
"translation": "데이터베이스 구성 오류가 발생하여 마이그레이션을 포기합니다: {Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Enter the Yugabyte database host(s)",
|
||||
"message": "Enter the Yugabyte database host(s)",
|
||||
"translation": "Yugabyte 데이터베이스 호스트를 입력하십시오"
|
||||
},
|
||||
{
|
||||
"id": "No host provided",
|
||||
"message": "No host provided",
|
||||
"translation": "호스트가 제공되지 않았습니다"
|
||||
},
|
||||
{
|
||||
"id": "Enter the Yugabyte database {Stringport_username_password_databasei_1}",
|
||||
"message": "Enter the Yugabyte database {Stringport_username_password_databasei_1}",
|
||||
"translation": "Yugabyte 데이터베이스 {Stringport_username_password_databasei_1}을 입력하십시오",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Stringport_username_password_databasei_1",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "[]string{\"port\", \"username\", \"password\", \"database\"}[i-1]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "No value provided",
|
||||
"message": "No value provided",
|
||||
"translation": "값이 제공되지 않았습니다"
|
||||
},
|
||||
{
|
||||
"id": "Error connecting to Yugabyte database: {Error}",
|
||||
"message": "Error connecting to Yugabyte database: {Error}",
|
||||
"translation": "Yugabyte 데이터베이스에 연결하는 중 오류가 발생했습니다: {Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Connected to Yugabyte. Schema is current.",
|
||||
"message": "Connected to Yugabyte. Schema is current.",
|
||||
"translation": "Yugabyte에 연결되었습니다. 스키마가 현재입니다."
|
||||
},
|
||||
{
|
||||
"id": "Error encoding config.toml: {Error}",
|
||||
"message": "Error encoding config.toml: {Error}",
|
||||
"translation": "config.toml을 인코딩하는 중 오류가 발생했습니다: {Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Error reading filemode of config.toml: {Error}",
|
||||
"message": "Error reading filemode of config.toml: {Error}",
|
||||
"translation": "config.toml의 파일 모드를 읽는 중 오류가 발생했습니다: {Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Error writing config.toml: {Error}",
|
||||
"message": "Error writing config.toml: {Error}",
|
||||
"translation": "config.toml을 쓰는 중 오류가 발생했습니다: {Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Restart Lotus Miner.",
|
||||
"message": "Restart Lotus Miner.",
|
||||
"translation": "로터스 마이너 재시작."
|
||||
},
|
||||
{
|
||||
"id": "Connected to Yugabyte",
|
||||
"message": "Connected to Yugabyte",
|
||||
"translation": "Yugabyte에 연결됨"
|
||||
},
|
||||
{
|
||||
"id": "Select the location of your lotus-miner config directory?",
|
||||
"message": "Select the location of your lotus-miner config directory?",
|
||||
"translation": "로터스 마이너 구성 디렉토리의 위치를 선택하시겠습니까?"
|
||||
},
|
||||
{
|
||||
"id": "Other",
|
||||
"message": "Other",
|
||||
"translation": "기타"
|
||||
},
|
||||
{
|
||||
"id": "Enter the path to the configuration directory used by lotus-miner",
|
||||
"message": "Enter the path to the configuration directory used by lotus-miner",
|
||||
"translation": "로터스 마이너에서 사용하는 구성 디렉토리의 경로를 입력하십시오"
|
||||
},
|
||||
{
|
||||
"id": "No path provided, abandoning migration",
|
||||
"message": "No path provided, abandoning migration",
|
||||
"translation": "경로가 제공되지 않았으므로 마이그레이션을 포기합니다"
|
||||
},
|
||||
{
|
||||
"id": "Cannot read the config.toml file in the provided directory, Error: {Error}",
|
||||
"message": "Cannot read the config.toml file in the provided directory, Error: {Error}",
|
||||
"translation": "제공된 디렉토리에서 config.toml 파일을 읽을 수 없습니다. 오류: {Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Read Miner Config",
|
||||
"message": "Read Miner Config",
|
||||
"translation": "마이너 구성 읽기"
|
||||
},
|
||||
{
|
||||
"id": "Completed Step: {Step}",
|
||||
"message": "Completed Step: {Step}",
|
||||
"translation": "단계 완료: {Step}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Step",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "step"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "This interactive tool migrates lotus-miner to Curio in 5 minutes.",
|
||||
"translation": "이 대화형 도구는 5분 안에 lotus-miner를 Curio로 이주합니다.",
|
||||
"message": "This interactive tool migrates lotus-miner to Curio in 5 minutes.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Each step needs your confirmation and can be reversed. Press Ctrl+C to exit at any time.",
|
||||
"translation": "각 단계는 확인이 필요하며 되돌릴 수 있습니다. 언제든지 Ctrl+C를 눌러 종료할 수 있습니다.",
|
||||
"message": "Each step needs your confirmation and can be reversed. Press Ctrl+C to exit at any time.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Use the arrow keys to navigate: ↓ ↑ → ←",
|
||||
"translation": "화살표 키를 사용하여 이동하세요: ↓ ↑ → ←",
|
||||
"message": "Use the arrow keys to navigate: ↓ ↑ → ←",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Lotus-Miner to Curio Migration.",
|
||||
"translation": "Lotus-Miner에서 Curio로 이주.",
|
||||
"message": "Lotus-Miner to Curio Migration.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Try the web interface with for further guided improvements.",
|
||||
"translation": "더 나은 안내를 위해 웹 인터페이스를 사용해보세요.",
|
||||
"message": "Try the web interface with for further guided improvements.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "You can now migrate your market node ({Boost}), if applicable.",
|
||||
"translation": "해당하는 경우 이제 시장 노드를 이주할 수 있습니다 ({Boost}).",
|
||||
"message": "You can now migrate your market node ({Boost}), if applicable.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Migrating config.toml to database.",
|
||||
"translation": "config.toml을 데이터베이스로 이주 중입니다.",
|
||||
"message": "Migrating config.toml to database.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error reading from database: {Error}. Aborting Migration.",
|
||||
"translation": "데이터베이스에서 읽는 중 오류 발생: {Error}. 마이그레이션 중단.",
|
||||
"message": "Error reading from database: {Error}. Aborting Migration.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "cannot read API: {Error}. Aborting Migration",
|
||||
"translation": "API를 읽을 수 없습니다: {Error}. 마이그레이션 중단",
|
||||
"message": "cannot read API: {Error}. Aborting Migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error saving config to layer: {Error}. Aborting Migration",
|
||||
"translation": "레이어에 구성을 저장하는 중 오류 발생: {Error}. 마이그레이션 중단",
|
||||
"message": "Error saving config to layer: {Error}. Aborting Migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Protocol Labs wants to improve the software you use. Tell the team you're using Curio.",
|
||||
"translation": "Protocol Labs는 당신이 사용하는 소프트웨어를 개선하고 싶어합니다. Curio를 사용 중이라고 팀에 알려주세요.",
|
||||
"message": "Protocol Labs wants to improve the software you use. Tell the team you're using Curio.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Select what you want to share with the Curio team.",
|
||||
"translation": "Curio 팀과 공유하고 싶은 것을 선택하세요.",
|
||||
"message": "Select what you want to share with the Curio team.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Individual Data: Miner ID, Curio version, net ({Mainnet} or {Testnet}). Signed.",
|
||||
"translation": "개별 데이터: 마이너 ID, Curio 버전, 네트워크 ({Mainnet} 또는 {Testnet}). 서명됨.",
|
||||
"message": "Individual Data: Miner ID, Curio version, net ({Mainnet} or {Testnet}). Signed.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Aggregate-Anonymous: version, net, and Miner power (bucketed).",
|
||||
"translation": "집계-익명: 버전, 네트워크, 그리고 마이너 파워 (버킷).",
|
||||
"message": "Aggregate-Anonymous: version, net, and Miner power (bucketed).",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Hint: I am someone running Curio on net.",
|
||||
"translation": "힌트: 네트워크에서 Curio를 실행 중인 사람입니다.",
|
||||
"message": "Hint: I am someone running Curio on net.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Nothing.",
|
||||
"translation": "아무것도 없습니다.",
|
||||
"message": "Nothing.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Aborting remaining steps.",
|
||||
"translation": "나머지 단계를 중단합니다.",
|
||||
"message": "Aborting remaining steps.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error connecting to lotus node: {Error}",
|
||||
"translation": "로터스 노드에 연결하는 중 오류 발생: {Error}",
|
||||
"message": "Error connecting to lotus node: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error getting miner power: {Error}",
|
||||
"translation": "마이너 파워를 가져오는 중 오류 발생: {Error}",
|
||||
"message": "Error getting miner power: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error marshalling message: {Error}",
|
||||
"translation": "메시지를 마샬하는 중 오류 발생: {Error}",
|
||||
"message": "Error marshalling message: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error getting miner info: {Error}",
|
||||
"translation": "마이너 정보를 가져오는 중 오류 발생: {Error}",
|
||||
"message": "Error getting miner info: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error signing message: {Error}",
|
||||
"translation": "메시지 서명 중 오류 발생: {Error}",
|
||||
"message": "Error signing message: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error sending message: {Error}",
|
||||
"translation": "메시지 전송 중 오류 발생: {Error}",
|
||||
"message": "Error sending message: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error sending message: Status {Status}, Message:",
|
||||
"translation": "메시지 전송 중 오류 발생: 상태 {Status}, 메시지:",
|
||||
"message": "Error sending message: Status {Status}, Message:",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Message sent.",
|
||||
"translation": "메시지가 전송되었습니다.",
|
||||
"message": "Message sent.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Documentation:",
|
||||
"translation": "문서:",
|
||||
"message": "Documentation:",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "The '{Base}' layer stores common configuration. All curio instances can include it in their {__layers} argument.",
|
||||
"translation": "'{Base}' 레이어에는 공통 구성이 저장됩니다. 모든 Curio 인스턴스는 {__layers} 인수에 포함시킬 수 있습니다.",
|
||||
"message": "The '{Base}' layer stores common configuration. All curio instances can include it in their {__layers} argument.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "You can add other layers for per-machine configuration changes.",
|
||||
"translation": "기계별 구성 변경을 위해 다른 레이어를 추가할 수 있습니다.",
|
||||
"message": "You can add other layers for per-machine configuration changes.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Join {Fil_curio_help} in Filecoin {Slack} for help.",
|
||||
"translation": "도움을 위해 Filecoin {Slack}의 {Fil_curio_help}에 가입하세요.",
|
||||
"message": "Join {Fil_curio_help} in Filecoin {Slack} for help.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Join {Fil_curio_dev} in Filecoin {Slack} to follow development and feedback!",
|
||||
"translation": "개발과 피드백을 따르려면 Filecoin {Slack}의 {Fil_curio_dev}에 가입하세요!",
|
||||
"message": "Join {Fil_curio_dev} in Filecoin {Slack} to follow development and feedback!",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Want PoST redundancy? Run many Curio instances with the '{Post}' layer.",
|
||||
"translation": "PoST 중복성이 필요하신가요? '{Post}' 레이어와 함께 여러 Curio 인스턴스를 실행하세요.",
|
||||
"message": "Want PoST redundancy? Run many Curio instances with the '{Post}' layer.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Point your browser to your web GUI to complete setup with {Boost} and advanced featues.",
|
||||
"translation": "브라우저를 웹 GUI로 이동하여 {Boost} 및 고급 기능으로 설정을 완료하세요.",
|
||||
"message": "Point your browser to your web GUI to complete setup with {Boost} and advanced featues.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "For SPs with multiple Miner IDs, run 1 migration per lotus-miner all to the same 1 database. The cluster will serve all Miner IDs.",
|
||||
"translation": "여러 마이너 ID가 있는 SP의 경우 각 lotus-miner당 1회 마이그레이션을 동일한 1개의 데이터베이스로 모두 실행하세요. 클러스터는 모든 마이너 ID를 제공합니다.",
|
||||
"message": "For SPs with multiple Miner IDs, run 1 migration per lotus-miner all to the same 1 database. The cluster will serve all Miner IDs.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Please start {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"translation": "데이터베이스 자격 증명이 {Toml}에 있으므로 이제 {Lotus_miner}를 시작하세요.",
|
||||
"message": "Please start {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Waiting for {Lotus_miner} to write sectors into Yugabyte.",
|
||||
"translation": "{Lotus_miner}가 Yugabyte에 섹터를 기록하도록 대기 중입니다.",
|
||||
"message": "Waiting for {Lotus_miner} to write sectors into Yugabyte.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "The sectors are in the database. The database is ready for {Curio}.",
|
||||
"translation": "섹터가 데이터베이스에 있습니다. 데이터베이스가 {Curio}를 위해 준비되었습니다.",
|
||||
"message": "The sectors are in the database. The database is ready for {Curio}.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Now shut down lotus-miner and move the systems to {Curio}.",
|
||||
"translation": "이제 lotus-miner를 종료하고 시스템을 {Curio}로 이동하세요.",
|
||||
"message": "Now shut down lotus-miner and move the systems to {Curio}.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Press return to continue",
|
||||
"translation": "계속하려면 리턴을 누르세요",
|
||||
"message": "Press return to continue",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Aborting migration.",
|
||||
"translation": "마이그레이션 중단.",
|
||||
"message": "Aborting migration.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Sectors verified. {I} sector locations found.",
|
||||
"translation": "섹터가 확인되었습니다. {I}개의 섹터 위치를 찾았습니다.",
|
||||
"message": "Sectors verified. {I} sector locations found.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Press return to update {Toml} with Yugabyte info. Backup the file now.",
|
||||
"translation": "{Toml}을 Yugabyte 정보로 업데이트하려면 리턴을 누르세요. 지금 파일을 백업하세요.",
|
||||
"message": "Press return to update {Toml} with Yugabyte info. Backup the file now.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "To start, ensure your sealing pipeline is drained and shut-down lotus-miner.",
|
||||
"translation": "시작하려면 밀봉 파이프라인이 비어 있고 lotus-miner가 종료되었는지 확인하세요.",
|
||||
"message": "To start, ensure your sealing pipeline is drained and shut-down lotus-miner.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Enter the path to the configuration directory used by {Lotus_miner}",
|
||||
"translation": "{Lotus_miner}에서 사용하는 구성 디렉터리 경로를 입력하세요.",
|
||||
"message": "Enter the path to the configuration directory used by {Lotus_miner}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Step Complete: {Step}",
|
||||
"translation": "단계 완료: {Step}",
|
||||
"message": "Step Complete: {Step}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Configuration 'base' was updated to include this miner's address and its wallet setup.",
|
||||
"translation": "이 마이너의 주소와 지갑 설정을 포함하도록 구성 'base'가 업데이트되었습니다.",
|
||||
"message": "Configuration 'base' was updated to include this miner's address and its wallet setup.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Compare the configurations {Base} to {MinerAddresses0}. Changes between the miner IDs other than wallet addreses should be a new, minimal layer for runners that need it.",
|
||||
"translation": "구성 {Base}를 {MinerAddresses0}과 비교하세요. 지갑 주소 이외의 마이너 ID 사이의 변경 사항은 필요한 실행자를 위한 새로운 최소한의 레이어여야 합니다.",
|
||||
"message": "Compare the configurations {Base} to {MinerAddresses0}. Changes between the miner IDs other than wallet addreses should be a new, minimal layer for runners that need it.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Configuration 'base' was created to include this miner's address and its wallet setup.",
|
||||
"translation": "이 마이너의 주소와 지갑 설정을 포함하도록 구성 'base'가 생성되었습니다.",
|
||||
"message": "Configuration 'base' was created to include this miner's address and its wallet setup.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Layer {LayerName} created.",
|
||||
"translation": "레이어 {LayerName}가 생성되었습니다.",
|
||||
"message": "Layer {LayerName} created.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "To work with the config: \\n",
|
||||
"translation": "구성을 사용하려면: \\n",
|
||||
"message": "To work with the config: \\n",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "To run Curio: With machine or cgroup isolation, use the command (with example layer selection):",
|
||||
"translation": "Curio를 실행하려면: 기계 또는 cgroup 격리를 사용하여 다음 명령을 사용하세요 (예제 레이어 선택과 함께):",
|
||||
"message": "To run Curio: With machine or cgroup isolation, use the command (with example layer selection):",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Try the web interface with {__layersgui} for further guided improvements.",
|
||||
"translation": "더 많은 안내를 위해 {__layersgui}를 사용하여 웹 인터페이스를 시도하세요.",
|
||||
"message": "Try the web interface with {__layersgui} for further guided improvements.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error connecting to lotus node: {Error} {Error_1}",
|
||||
"translation": "lotus 노드에 연결하는 중 오류 발생: {Error} {Error_1}",
|
||||
"message": "Error connecting to lotus node: {Error} {Error_1}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "could not get API info for FullNode: {Err}",
|
||||
"translation": "FullNode의 API 정보를 가져올 수 없습니다: {Err}",
|
||||
"message": "could not get API info for FullNode: {Err}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error getting token: {Error}",
|
||||
"translation": "토큰을 가져오는 중 오류 발생: {Error}",
|
||||
"message": "Error getting token: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
||||
"translation": "Filecoin {Slack} 채널: {Fil_curio_help} 및 {Fil_curio_dev}",
|
||||
"message": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
||||
"translation": "'{Post}' 레이어로 여러 Curio 인스턴스를 시작하여 중복성을 확보하세요.",
|
||||
"message": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
||||
"translation": "한 개의 데이터베이스는 여러 광부 ID를 제공할 수 있습니다: 각 lotus-miner에 대해 마이그레이션을 실행하세요.",
|
||||
"message": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"translation": "데이터베이스 자격 증명이 {Toml}에 입력되었으므로 지금 {Lotus_miner}을 시작하거나 다시 시작하세요.",
|
||||
"message": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error interpreting miner ID: {Error}: ID: {String}",
|
||||
"translation": "광부 ID를 해석하는 중 오류 발생: {Error}: ID: {String}",
|
||||
"message": "Error interpreting miner ID: {Error}: ID: {String}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Enabling Sector Indexing in the database.",
|
||||
"translation": "데이터베이스에서 Sector Indexing을 활성화합니다.",
|
||||
"message": "Enabling Sector Indexing in the database.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error expanding path: {Error}",
|
||||
"translation": "경로를 확장하는 중 오류 발생: {Error}",
|
||||
"message": "Error expanding path: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Could not create repo from directory: {Error}. Aborting migration",
|
||||
"translation": "디렉토리에서 저장소를 생성할 수 없습니다: {Error}. 마이그레이션을 중단합니다.",
|
||||
"message": "Could not create repo from directory: {Error}. Aborting migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
||||
"translation": "광부 저장소를 잠금 해제할 수 없습니다. 귀하의 광부를 중지해야 합니다: {Error}\n 마이그레이션을 중단합니다.",
|
||||
"message": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "To work with the config:",
|
||||
"translation": "구성 파일을 사용하려면:",
|
||||
"message": "To work with the config:",
|
||||
"placeholder": null
|
||||
}
|
||||
]
|
||||
}
|
89
cmd/curio/internal/translations/locales/ko/out.gotext.json
Normal file
89
cmd/curio/internal/translations/locales/ko/out.gotext.json
Normal file
@ -0,0 +1,89 @@
|
||||
{
|
||||
"language": "ko",
|
||||
"messages": [
|
||||
{
|
||||
"id": "Try the web interface with {__layersgui} for further guided improvements.",
|
||||
"translation": "",
|
||||
"message": "Try the web interface with {__layersgui} for further guided improvements.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error connecting to lotus node: {Error} {Error_1}",
|
||||
"translation": "",
|
||||
"message": "Error connecting to lotus node: {Error} {Error_1}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "could not get API info for FullNode: {Err}",
|
||||
"translation": "",
|
||||
"message": "could not get API info for FullNode: {Err}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error getting token: {Error}",
|
||||
"translation": "",
|
||||
"message": "Error getting token: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
||||
"translation": "",
|
||||
"message": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
||||
"translation": "",
|
||||
"message": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
||||
"translation": "",
|
||||
"message": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"translation": "",
|
||||
"message": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error interpreting miner ID: {Error}: ID: {String}",
|
||||
"translation": "",
|
||||
"message": "Error interpreting miner ID: {Error}: ID: {String}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Enabling Sector Indexing in the database.",
|
||||
"translation": "",
|
||||
"message": "Enabling Sector Indexing in the database.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error expanding path: {Error}",
|
||||
"translation": "",
|
||||
"message": "Error expanding path: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Could not create repo from directory: {Error}. Aborting migration",
|
||||
"translation": "",
|
||||
"message": "Could not create repo from directory: {Error}. Aborting migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
||||
"translation": "",
|
||||
"message": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "To work with the config:",
|
||||
"translation": "",
|
||||
"message": "To work with the config:",
|
||||
"placeholder": null
|
||||
}
|
||||
]
|
||||
}
|
704
cmd/curio/internal/translations/locales/zh/messages.gotext.json
Normal file
704
cmd/curio/internal/translations/locales/zh/messages.gotext.json
Normal file
@ -0,0 +1,704 @@
|
||||
{
|
||||
"language": "zh",
|
||||
"messages": [
|
||||
{
|
||||
"id": "This interactive tool will walk you through migration of Curio.\nPress Ctrl+C to exit at any time.",
|
||||
"message": "This interactive tool will walk you through migration of Curio.\nPress Ctrl+C to exit at any time.",
|
||||
"translation": "此互动工具将引导您完成Curio的迁移。\n随时按Ctrl+C退出。"
|
||||
},
|
||||
{
|
||||
"id": "This tool confirms each action it does.",
|
||||
"message": "This tool confirms each action it does.",
|
||||
"translation": "此工具确认其执行的每个操作。"
|
||||
},
|
||||
{
|
||||
"id": "Ctrl+C pressed in Terminal",
|
||||
"message": "Ctrl+C pressed in Terminal",
|
||||
"translation": "在终端中按下Ctrl+C"
|
||||
},
|
||||
{
|
||||
"id": "Verifying Sectors exist in Yugabyte.",
|
||||
"message": "Verifying Sectors exist in Yugabyte.",
|
||||
"translation": "正在验证Yugabyte中的扇区是否存在。"
|
||||
},
|
||||
{
|
||||
"id": "Error verifying sectors: {Error}",
|
||||
"message": "Error verifying sectors: {Error}",
|
||||
"translation": "验证扇区时出错:{Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Sectors verified. {I} sectors found.",
|
||||
"message": "Sectors verified. {I} sectors found.",
|
||||
"translation": "已验证扇区。找到了{I}个扇区。",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "I",
|
||||
"string": "%[1]d",
|
||||
"type": "[]int",
|
||||
"underlyingType": "[]int",
|
||||
"argNum": 1,
|
||||
"expr": "i"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Never remove the database info from the config.toml for lotus-miner as it avoids double PoSt.",
|
||||
"message": "Never remove the database info from the config.toml for lotus-miner as it avoids double PoSt.",
|
||||
"translation": "从config.toml中永远不要删除lotus-miner的数据库信息,因为它避免了双PoSt。"
|
||||
},
|
||||
{
|
||||
"id": "Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)",
|
||||
"message": "Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)",
|
||||
"translation": "输入连接到您的Yugabyte数据库安装的信息(https://download.yugabyte.com/)"
|
||||
},
|
||||
{
|
||||
"id": "Host: {Hosts_}",
|
||||
"message": "Host: {Hosts_}",
|
||||
"translation": "主机:{Hosts_}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Hosts_",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "strings.Join(harmonycfg.Hosts, \",\")"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Port: {Port}",
|
||||
"message": "Port: {Port}",
|
||||
"translation": "端口:{Port}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Port",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "harmonycfg.Port"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Username: {Username}",
|
||||
"message": "Username: {Username}",
|
||||
"translation": "用户名:{Username}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Username",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "harmonycfg.Username"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Password: {Password}",
|
||||
"message": "Password: {Password}",
|
||||
"translation": "密码:{Password}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Password",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "harmonycfg.Password"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Database: {Database}",
|
||||
"message": "Database: {Database}",
|
||||
"translation": "数据库:{Database}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Database",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "harmonycfg.Database"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Continue to connect and update schema.",
|
||||
"message": "Continue to connect and update schema.",
|
||||
"translation": "继续连接和更新架构。"
|
||||
},
|
||||
{
|
||||
"id": "Database config error occurred, abandoning migration: {Error}",
|
||||
"message": "Database config error occurred, abandoning migration: {Error}",
|
||||
"translation": "发生数据库配置错误,放弃迁移:{Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Enter the Yugabyte database host(s)",
|
||||
"message": "Enter the Yugabyte database host(s)",
|
||||
"translation": "输入Yugabyte数据库主机(S)"
|
||||
},
|
||||
{
|
||||
"id": "No host provided",
|
||||
"message": "No host provided",
|
||||
"translation": "未提供主机"
|
||||
},
|
||||
{
|
||||
"id": "Enter the Yugabyte database {Stringport_username_password_databasei_1}",
|
||||
"message": "Enter the Yugabyte database {Stringport_username_password_databasei_1}",
|
||||
"translation": "输入Yugabyte数据库 {Stringport_username_password_databasei_1}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Stringport_username_password_databasei_1",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "[]string{\"port\", \"username\", \"password\", \"database\"}[i-1]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "No value provided",
|
||||
"message": "No value provided",
|
||||
"translation": "未提供值"
|
||||
},
|
||||
{
|
||||
"id": "Error connecting to Yugabyte database: {Error}",
|
||||
"message": "Error connecting to Yugabyte database: {Error}",
|
||||
"translation": "连接到Yugabyte数据库时出错:{Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Connected to Yugabyte. Schema is current.",
|
||||
"message": "Connected to Yugabyte. Schema is current.",
|
||||
"translation": "已连接到Yugabyte。模式是当前的。"
|
||||
},
|
||||
{
|
||||
"id": "Error encoding config.toml: {Error}",
|
||||
"message": "Error encoding config.toml: {Error}",
|
||||
"translation": "编码config.toml时出错:{Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Error reading filemode of config.toml: {Error}",
|
||||
"message": "Error reading filemode of config.toml: {Error}",
|
||||
"translation": "读取config.toml文件模式时出错:{Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Error writing config.toml: {Error}",
|
||||
"message": "Error writing config.toml: {Error}",
|
||||
"translation": "写入config.toml时出错:{Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Restart Lotus Miner.",
|
||||
"message": "Restart Lotus Miner.",
|
||||
"translation": "重新启动Lotus Miner。"
|
||||
},
|
||||
{
|
||||
"id": "Connected to Yugabyte",
|
||||
"message": "Connected to Yugabyte",
|
||||
"translation": "已连接到Yugabyte"
|
||||
},
|
||||
{
|
||||
"id": "Select the location of your lotus-miner config directory?",
|
||||
"message": "Select the location of your lotus-miner config directory?",
|
||||
"translation": "选择您的lotus-miner配置目录的位置?"
|
||||
},
|
||||
{
|
||||
"id": "Other",
|
||||
"message": "Other",
|
||||
"translation": "其他"
|
||||
},
|
||||
{
|
||||
"id": "Enter the path to the configuration directory used by lotus-miner",
|
||||
"message": "Enter the path to the configuration directory used by lotus-miner",
|
||||
"translation": "输入lotus-miner使用的配置目录的路径"
|
||||
},
|
||||
{
|
||||
"id": "No path provided, abandoning migration",
|
||||
"message": "No path provided, abandoning migration",
|
||||
"translation": "未提供路径,放弃迁移"
|
||||
},
|
||||
{
|
||||
"id": "Cannot read the config.toml file in the provided directory, Error: {Error}",
|
||||
"message": "Cannot read the config.toml file in the provided directory, Error: {Error}",
|
||||
"translation": "无法读取提供的目录中的config.toml文件,错误:{Error}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "Read Miner Config",
|
||||
"message": "Read Miner Config",
|
||||
"translation": "读取矿工配置"
|
||||
},
|
||||
{
|
||||
"id": "Completed Step: {Step}",
|
||||
"message": "Completed Step: {Step}",
|
||||
"translation": "完成步骤:{Step}",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Step",
|
||||
"string": "%[1]s",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "step"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "This interactive tool migrates lotus-miner to Curio in 5 minutes.",
|
||||
"translation": "这个交互式工具可以在5分钟内将lotus-miner迁移到Curio。",
|
||||
"message": "This interactive tool migrates lotus-miner to Curio in 5 minutes.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Each step needs your confirmation and can be reversed. Press Ctrl+C to exit at any time.",
|
||||
"translation": "每一步都需要您的确认,并且可以撤销。随时按Ctrl+C退出。",
|
||||
"message": "Each step needs your confirmation and can be reversed. Press Ctrl+C to exit at any time.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Use the arrow keys to navigate: ↓ ↑ → ←",
|
||||
"translation": "使用箭头键进行导航:↓ ↑ → ←",
|
||||
"message": "Use the arrow keys to navigate: ↓ ↑ → ←",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Lotus-Miner to Curio Migration.",
|
||||
"translation": "Lotus-Miner到Curio迁移。",
|
||||
"message": "Lotus-Miner to Curio Migration.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Try the web interface with for further guided improvements.",
|
||||
"translation": "尝试使用网页界面进行进一步的指导改进。",
|
||||
"message": "Try the web interface with for further guided improvements.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "You can now migrate your market node ({Boost}), if applicable.",
|
||||
"translation": "如果适用,您现在可以迁移您的市场节点({Boost})。",
|
||||
"message": "You can now migrate your market node ({Boost}), if applicable.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Migrating config.toml to database.",
|
||||
"translation": "正在将config.toml迁移到数据库。",
|
||||
"message": "Migrating config.toml to database.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error reading from database: {Error}. Aborting Migration.",
|
||||
"translation": "读取数据库时出错:{Error}。正在中止迁移。",
|
||||
"message": "Error reading from database: {Error}. Aborting Migration.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "cannot read API: {Error}. Aborting Migration",
|
||||
"translation": "无法读取API:{Error}。正在中止迁移",
|
||||
"message": "cannot read API: {Error}. Aborting Migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error saving config to layer: {Error}. Aborting Migration",
|
||||
"translation": "保存配置到层时出错:{Error}。正在中止迁移",
|
||||
"message": "Error saving config to layer: {Error}. Aborting Migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Protocol Labs wants to improve the software you use. Tell the team you're using Curio.",
|
||||
"translation": "Protocol Labs希望改进您使用的软件。告诉团队您正在使用Curio。",
|
||||
"message": "Protocol Labs wants to improve the software you use. Tell the team you're using Curio.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Select what you want to share with the Curio team.",
|
||||
"translation": "选择您想与Curio团队分享的内容。",
|
||||
"message": "Select what you want to share with the Curio team.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Individual Data: Miner ID, Curio version, net ({Mainnet} or {Testnet}). Signed.",
|
||||
"translation": "个人数据:矿工ID、Curio版本、网络({Mainnet}或{Testnet})。已签名。",
|
||||
"message": "Individual Data: Miner ID, Curio version, net ({Mainnet} or {Testnet}). Signed.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Aggregate-Anonymous: version, net, and Miner power (bucketed).",
|
||||
"translation": "聚合-匿名:版本、网络和矿工功率(分桶)。",
|
||||
"message": "Aggregate-Anonymous: version, net, and Miner power (bucketed).",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Hint: I am someone running Curio on net.",
|
||||
"translation": "提示:我是在网络上运行Curio的人。",
|
||||
"message": "Hint: I am someone running Curio on net.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Nothing.",
|
||||
"translation": "没有。",
|
||||
"message": "Nothing.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Aborting remaining steps.",
|
||||
"translation": "中止剩余步骤。",
|
||||
"message": "Aborting remaining steps.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error connecting to lotus node: {Error}",
|
||||
"translation": "连接到莲花节点时出错:{Error}",
|
||||
"message": "Error connecting to lotus node: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error getting miner power: {Error}",
|
||||
"translation": "获取矿工功率时出错:{Error}",
|
||||
"message": "Error getting miner power: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error marshalling message: {Error}",
|
||||
"translation": "整理消息时出错:{Error}",
|
||||
"message": "Error marshalling message: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error getting miner info: {Error}",
|
||||
"translation": "获取矿工信息时出错:{Error}",
|
||||
"message": "Error getting miner info: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error signing message: {Error}",
|
||||
"translation": "签署消息时出错:{Error}",
|
||||
"message": "Error signing message: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error sending message: {Error}",
|
||||
"translation": "发送消息时出错:{Error}",
|
||||
"message": "Error sending message: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error sending message: Status {Status}, Message:",
|
||||
"translation": "发送消息时出错:状态{Status},消息:",
|
||||
"message": "Error sending message: Status {Status}, Message:",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Message sent.",
|
||||
"translation": "消息已发送。",
|
||||
"message": "Message sent.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Documentation:",
|
||||
"translation": "文档:",
|
||||
"message": "Documentation:",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "The '{Base}' layer stores common configuration. All curio instances can include it in their {__layers} argument.",
|
||||
"translation": "'{Base}'层存储通用配置。所有Curio实例都可以在其{__layers}参数中包含它。",
|
||||
"message": "The '{Base}' layer stores common configuration. All curio instances can include it in their {__layers} argument.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "You can add other layers for per-machine configuration changes.",
|
||||
"translation": "您可以添加其他层进行每台机器的配置更改。",
|
||||
"message": "You can add other layers for per-machine configuration changes.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Join {Fil_curio_help} in Filecoin {Slack} for help.",
|
||||
"translation": "加入Filecoin {Slack}中的{Fil_curio_help}寻求帮助。",
|
||||
"message": "Join {Fil_curio_help} in Filecoin {Slack} for help.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Join {Fil_curio_dev} in Filecoin {Slack} to follow development and feedback!",
|
||||
"translation": "加入Filecoin {Slack}中的{Fil_curio_dev}来跟踪开发和反馈!",
|
||||
"message": "Join {Fil_curio_dev} in Filecoin {Slack} to follow development and feedback!",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Want PoST redundancy? Run many Curio instances with the '{Post}' layer.",
|
||||
"translation": "需要PoST冗余?使用'{Post}'层运行多个Curio实例。",
|
||||
"message": "Want PoST redundancy? Run many Curio instances with the '{Post}' layer.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Point your browser to your web GUI to complete setup with {Boost} and advanced featues.",
|
||||
"translation": "将您的浏览器指向您的网络GUI,以使用{Boost}和高级功能完成设置。",
|
||||
"message": "Point your browser to your web GUI to complete setup with {Boost} and advanced featues.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "For SPs with multiple Miner IDs, run 1 migration per lotus-miner all to the same 1 database. The cluster will serve all Miner IDs.",
|
||||
"translation": "对于具有多个矿工ID的SP,针对所有lotus-miner运行1次迁移到同一个数据库。集群将服务所有矿工ID。",
|
||||
"message": "For SPs with multiple Miner IDs, run 1 migration per lotus-miner all to the same 1 database. The cluster will serve all Miner IDs.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Please start {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"translation": "现在数据库凭证在{Toml}中,请启动{Lotus_miner}。",
|
||||
"message": "Please start {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Waiting for {Lotus_miner} to write sectors into Yugabyte.",
|
||||
"translation": "等待{Lotus_miner}将扇区写入Yugabyte。",
|
||||
"message": "Waiting for {Lotus_miner} to write sectors into Yugabyte.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "The sectors are in the database. The database is ready for {Curio}.",
|
||||
"translation": "扇区在数据库中。数据库已准备好用于{Curio}。",
|
||||
"message": "The sectors are in the database. The database is ready for {Curio}.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Now shut down lotus-miner and move the systems to {Curio}.",
|
||||
"translation": "现在关闭lotus-miner并将系统移至{Curio}。",
|
||||
"message": "Now shut down lotus-miner and move the systems to {Curio}.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Press return to continue",
|
||||
"translation": "按回车继续",
|
||||
"message": "Press return to continue",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Aborting migration.",
|
||||
"translation": "中止迁移。",
|
||||
"message": "Aborting migration.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Sectors verified. {I} sector locations found.",
|
||||
"translation": "扇区已验证。发现了{I}个扇区位置。",
|
||||
"message": "Sectors verified. {I} sector locations found.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Press return to update {Toml} with Yugabyte info. Backup the file now.",
|
||||
"translation": "按回车更新{Toml}以获取Yugabyte信息。现在备份文件。",
|
||||
"message": "Press return to update {Toml} with Yugabyte info. Backup the file now.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "To start, ensure your sealing pipeline is drained and shut-down lotus-miner.",
|
||||
"translation": "开始之前,请确保您的密封管道已排空并关闭lotus-miner。",
|
||||
"message": "To start, ensure your sealing pipeline is drained and shut-down lotus-miner.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Enter the path to the configuration directory used by {Lotus_miner}",
|
||||
"translation": "输入{Lotus_miner}使用的配置目录的路径",
|
||||
"message": "Enter the path to the configuration directory used by {Lotus_miner}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Step Complete: {Step}",
|
||||
"translation": "步骤完成:{Step}",
|
||||
"message": "Step Complete: {Step}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Configuration 'base' was updated to include this miner's address and its wallet setup.",
|
||||
"translation": "配置'base'已更新,包含了这个矿工的地址和其钱包设置。",
|
||||
"message": "Configuration 'base' was updated to include this miner's address and its wallet setup.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Compare the configurations {Base} to {MinerAddresses0}. Changes between the miner IDs other than wallet addreses should be a new, minimal layer for runners that need it.",
|
||||
"translation": "比较配置{Base}和{MinerAddresses0}。矿工ID之间除了钱包地址的变化应该是需要的运行者的一个新的、最小的层。",
|
||||
"message": "Compare the configurations {Base} to {MinerAddresses0}. Changes between the miner IDs other than wallet addreses should be a new, minimal layer for runners that need it.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Configuration 'base' was created to include this miner's address and its wallet setup.",
|
||||
"translation": "配置'base'已创建,包括了这个矿工的地址和其钱包设置。",
|
||||
"message": "Configuration 'base' was created to include this miner's address and its wallet setup.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Layer {LayerName} created.",
|
||||
"translation": "层{LayerName}已创建。",
|
||||
"message": "Layer {LayerName} created.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "To work with the config: \\n",
|
||||
"translation": "要使用配置:\\n",
|
||||
"message": "To work with the config: \\n",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "To run Curio: With machine or cgroup isolation, use the command (with example layer selection):",
|
||||
"translation": "运行Curio:使用机器或cgroup隔离,使用命令(附带示例层选择):",
|
||||
"message": "To run Curio: With machine or cgroup isolation, use the command (with example layer selection):",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Try the web interface with {__layersgui} for further guided improvements.",
|
||||
"translation": "尝试使用{__layersgui}的Web界面进行进一步引导式改进。",
|
||||
"message": "Try the web interface with {__layersgui} for further guided improvements.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error connecting to lotus node: {Error} {Error_1}",
|
||||
"translation": "连接到lotus节点时出错:{Error} {Error_1}",
|
||||
"message": "Error connecting to lotus node: {Error} {Error_1}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "could not get API info for FullNode: {Err}",
|
||||
"translation": "无法获取FullNode的API信息:{Err}",
|
||||
"message": "could not get API info for FullNode: {Err}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error getting token: {Error}",
|
||||
"translation": "获取令牌时出错:{Error}",
|
||||
"message": "Error getting token: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
||||
"translation": "Filecoin {Slack} 频道:{Fil_curio_help} 和 {Fil_curio_dev}",
|
||||
"message": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
||||
"translation": "使用'{Post}'层启动多个Curio实例以实现冗余。",
|
||||
"message": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
||||
"translation": "一个数据库可以服务多个矿工ID:为每个lotus-miner运行迁移。",
|
||||
"message": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"translation": "请立即启动(或重新启动){Lotus_miner},因为数据库凭据已在{Toml}中。",
|
||||
"message": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error interpreting miner ID: {Error}: ID: {String}",
|
||||
"translation": "解释矿工ID时出错:{Error}:ID:{String}",
|
||||
"message": "Error interpreting miner ID: {Error}: ID: {String}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Enabling Sector Indexing in the database.",
|
||||
"translation": "在数据库中启用扇区索引。",
|
||||
"message": "Enabling Sector Indexing in the database.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error expanding path: {Error}",
|
||||
"translation": "扩展路径时出错:{Error}",
|
||||
"message": "Error expanding path: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Could not create repo from directory: {Error}. Aborting migration",
|
||||
"translation": "无法从目录创建repo:{Error}。 中止迁移",
|
||||
"message": "Could not create repo from directory: {Error}. Aborting migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
||||
"translation": "无法锁定矿工repo。 您的矿工必须停止:{Error}\n 中止迁移",
|
||||
"message": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "To work with the config:",
|
||||
"translation": "要使用配置:",
|
||||
"message": "To work with the config:",
|
||||
"placeholder": null
|
||||
}
|
||||
]
|
||||
}
|
89
cmd/curio/internal/translations/locales/zh/out.gotext.json
Normal file
89
cmd/curio/internal/translations/locales/zh/out.gotext.json
Normal file
@ -0,0 +1,89 @@
|
||||
{
|
||||
"language": "zh",
|
||||
"messages": [
|
||||
{
|
||||
"id": "Try the web interface with {__layersgui} for further guided improvements.",
|
||||
"translation": "",
|
||||
"message": "Try the web interface with {__layersgui} for further guided improvements.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error connecting to lotus node: {Error} {Error_1}",
|
||||
"translation": "",
|
||||
"message": "Error connecting to lotus node: {Error} {Error_1}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "could not get API info for FullNode: {Err}",
|
||||
"translation": "",
|
||||
"message": "could not get API info for FullNode: {Err}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error getting token: {Error}",
|
||||
"translation": "",
|
||||
"message": "Error getting token: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
||||
"translation": "",
|
||||
"message": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
||||
"translation": "",
|
||||
"message": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
||||
"translation": "",
|
||||
"message": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"translation": "",
|
||||
"message": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error interpreting miner ID: {Error}: ID: {String}",
|
||||
"translation": "",
|
||||
"message": "Error interpreting miner ID: {Error}: ID: {String}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Enabling Sector Indexing in the database.",
|
||||
"translation": "",
|
||||
"message": "Enabling Sector Indexing in the database.",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Error expanding path: {Error}",
|
||||
"translation": "",
|
||||
"message": "Error expanding path: {Error}",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Could not create repo from directory: {Error}. Aborting migration",
|
||||
"translation": "",
|
||||
"message": "Could not create repo from directory: {Error}. Aborting migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
||||
"translation": "",
|
||||
"message": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "To work with the config:",
|
||||
"translation": "",
|
||||
"message": "To work with the config:",
|
||||
"placeholder": null
|
||||
}
|
||||
]
|
||||
}
|
27
cmd/curio/internal/translations/translations.go
Normal file
27
cmd/curio/internal/translations/translations.go
Normal file
@ -0,0 +1,27 @@
|
||||
// Usage:
|
||||
// To UPDATE translations:
|
||||
//
|
||||
// 1. add/change strings in guidedsetup folder that use d.T() or d.say().
|
||||
//
|
||||
// 2. run `go generate` in the cmd/curio/internal/translations/ folder.
|
||||
//
|
||||
// 3. ChatGPT 3.5 can translate the ./locales/??/out.gotext.json files'
|
||||
// which ONLY include the un-translated messages.
|
||||
// APPEND to the messages.gotext.json files's array.
|
||||
//
|
||||
// ChatGPT fuss:
|
||||
// - on a good day, you may need to hit "continue generating".
|
||||
// - > 60? you'll need to give it sections of the file.
|
||||
//
|
||||
// 4. Re-import with `go generate` again.
|
||||
//
|
||||
// To ADD a language:
|
||||
// 1. Add it to the list in updateLang.sh
|
||||
// 2. Run `go generate` in the cmd/curio/internal/translations/ folder.
|
||||
// 3. Follow the "Update translations" steps here.
|
||||
// 4. Code will auto-detect the new language and use it.
|
||||
//
|
||||
// FUTURE Reliability: OpenAPI automation.
|
||||
package translations
|
||||
|
||||
//go:generate ./updateLang.sh
|
8
cmd/curio/internal/translations/updateLang.sh
Executable file
8
cmd/curio/internal/translations/updateLang.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
#OP: Only run if some file in ../guidedsetup* is newer than catalog.go
|
||||
# Change this condition if using translations more widely.
|
||||
if [ "$(find ../../guidedsetup/* -newermt "$(date -d '1 minute ago')" -newer catalog.go)" ] || [ "$(find locales/* -newermt "$(date -d '1 minute ago')" -newer catalog.go)" ]; then
|
||||
gotext -srclang=en update -out=catalog.go -lang=en,zh,ko github.com/filecoin-project/lotus/cmd/curio/guidedsetup
|
||||
go run knowns/main.go locales/zh locales/ko
|
||||
fi
|
@ -16,7 +16,8 @@ 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/cmd/curio/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/guidedsetup"
|
||||
"github.com/filecoin-project/lotus/lib/lotuslog"
|
||||
"github.com/filecoin-project/lotus/lib/tracing"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
@ -24,7 +25,7 @@ import (
|
||||
|
||||
var log = logging.Logger("main")
|
||||
|
||||
func SetupCloseHandler() {
|
||||
func setupCloseHandler() {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
@ -36,7 +37,6 @@ func SetupCloseHandler() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
SetupCloseHandler()
|
||||
|
||||
lotuslog.SetupLogLevels()
|
||||
|
||||
@ -48,10 +48,12 @@ func main() {
|
||||
configCmd,
|
||||
testCmd,
|
||||
webCmd,
|
||||
guidedsetup.GuidedsetupCmd,
|
||||
configMigrateCmd,
|
||||
sealCmd,
|
||||
}
|
||||
|
||||
jaeger := tracing.SetupJaegerTracing("lotus")
|
||||
jaeger := tracing.SetupJaegerTracing("curio")
|
||||
defer func() {
|
||||
if jaeger != nil {
|
||||
_ = jaeger.ForceFlush(context.Background())
|
||||
@ -65,7 +67,7 @@ func main() {
|
||||
if jaeger != nil {
|
||||
_ = jaeger.Shutdown(cctx.Context)
|
||||
}
|
||||
jaeger = tracing.SetupJaegerTracing("lotus/" + cmd.Name)
|
||||
jaeger = tracing.SetupJaegerTracing("curio/" + cmd.Name)
|
||||
|
||||
if cctx.IsSet("color") {
|
||||
color.NoColor = !cctx.Bool("color")
|
||||
@ -80,10 +82,14 @@ func main() {
|
||||
}
|
||||
|
||||
app := &cli.App{
|
||||
Name: "lotus-provider",
|
||||
Name: "curio",
|
||||
Usage: "Filecoin decentralized storage network provider",
|
||||
Version: build.UserVersion(),
|
||||
EnableBashCompletion: true,
|
||||
Before: func(c *cli.Context) error {
|
||||
setupCloseHandler()
|
||||
return nil
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
// examined in the Before above
|
||||
@ -93,48 +99,45 @@ func main() {
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "panic-reports",
|
||||
EnvVars: []string{"LOTUS_PANIC_REPORT_PATH"},
|
||||
EnvVars: []string{"CURIO_PANIC_REPORT_PATH"},
|
||||
Hidden: true,
|
||||
Value: "~/.lotusprovider", // should follow --repo default
|
||||
Value: "~/.curio", // should follow --repo default
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "db-host",
|
||||
EnvVars: []string{"LOTUS_DB_HOST"},
|
||||
EnvVars: []string{"CURIO_DB_HOST", "CURIO_HARMONYDB_HOSTS"},
|
||||
Usage: "Command separated list of hostnames for yugabyte cluster",
|
||||
Value: "yugabyte",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "db-name",
|
||||
EnvVars: []string{"LOTUS_DB_NAME", "LOTUS_HARMONYDB_HOSTS"},
|
||||
EnvVars: []string{"CURIO_DB_NAME", "CURIO_HARMONYDB_NAME"},
|
||||
Value: "yugabyte",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "db-user",
|
||||
EnvVars: []string{"LOTUS_DB_USER", "LOTUS_HARMONYDB_USERNAME"},
|
||||
EnvVars: []string{"CURIO_DB_USER", "CURIO_HARMONYDB_USERNAME"},
|
||||
Value: "yugabyte",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "db-password",
|
||||
EnvVars: []string{"LOTUS_DB_PASSWORD", "LOTUS_HARMONYDB_PASSWORD"},
|
||||
EnvVars: []string{"CURIO_DB_PASSWORD", "CURIO_HARMONYDB_PASSWORD"},
|
||||
Value: "yugabyte",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "db-port",
|
||||
EnvVars: []string{"LOTUS_DB_PORT", "LOTUS_HARMONYDB_PORT"},
|
||||
EnvVars: []string{"CURIO_DB_PORT", "CURIO_HARMONYDB_PORT"},
|
||||
Hidden: true,
|
||||
Value: "5433",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: deps.FlagRepoPath,
|
||||
EnvVars: []string{"LOTUS_REPO_PATH"},
|
||||
Value: "~/.lotusprovider",
|
||||
EnvVars: []string{"CURIO_REPO_PATH"},
|
||||
Value: "~/.curio",
|
||||
},
|
||||
cliutil.FlagVeryVerbose,
|
||||
},
|
||||
Commands: append(local, lcli.CommonCommands...),
|
||||
Before: func(c *cli.Context) error {
|
||||
return nil
|
||||
},
|
||||
After: func(c *cli.Context) error {
|
||||
if r := recover(); r != nil {
|
||||
p, err := homedir.Expand(c.String(FlagMinerRepo))
|
||||
@ -143,7 +146,7 @@ func main() {
|
||||
panic(r)
|
||||
}
|
||||
|
||||
// Generate report in LOTUS_PATH and re-raise panic
|
||||
// Generate report in CURIO_PATH and re-raise panic
|
||||
build.GeneratePanicReport(c.String("panic-reports"), p, c.App.Name)
|
||||
panic(r)
|
||||
}
|
||||
@ -151,6 +154,6 @@ func main() {
|
||||
},
|
||||
}
|
||||
app.Setup()
|
||||
app.Metadata["repoType"] = repo.Provider
|
||||
app.Metadata["repoType"] = repo.Curio
|
||||
lcli.RunApp(app)
|
||||
}
|
71
cmd/curio/migrate.go
Normal file
71
cmd/curio/migrate.go
Normal file
@ -0,0 +1,71 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/guidedsetup"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
)
|
||||
|
||||
var configMigrateCmd = &cli.Command{
|
||||
Name: "from-miner",
|
||||
Usage: "Express a database config (for curio) from an existing miner.",
|
||||
Description: "Express a database config (for curio) from an existing miner.",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: FlagMinerRepo,
|
||||
Aliases: []string{FlagMinerRepoDeprecation},
|
||||
EnvVars: []string{"LOTUS_MINER_PATH", "LOTUS_STORAGE_PATH"},
|
||||
Value: "~/.lotusminer",
|
||||
Usage: fmt.Sprintf("Specify miner repo path. flag(%s) and env(LOTUS_STORAGE_PATH) are DEPRECATION, will REMOVE SOON", FlagMinerRepoDeprecation),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "repo",
|
||||
EnvVars: []string{"LOTUS_PATH"},
|
||||
Hidden: true,
|
||||
Value: "~/.lotus",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "to-layer",
|
||||
Aliases: []string{"t"},
|
||||
Usage: "The layer name for this data push. 'base' is recommended for single-miner setup.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "overwrite",
|
||||
Aliases: []string{"o"},
|
||||
Usage: "Use this with --to-layer to replace an existing layer",
|
||||
},
|
||||
},
|
||||
Action: fromMiner,
|
||||
}
|
||||
|
||||
const (
|
||||
FlagMinerRepo = "miner-repo"
|
||||
)
|
||||
|
||||
const FlagMinerRepoDeprecation = "storagerepo"
|
||||
|
||||
func fromMiner(cctx *cli.Context) (err error) {
|
||||
minerRepoPath := cctx.String(FlagMinerRepo)
|
||||
layerName := cctx.String("to-layer")
|
||||
overwrite := cctx.Bool("overwrite")
|
||||
|
||||
// Populate API Key
|
||||
_, header, err := cliutil.GetRawAPI(cctx, repo.FullNode, "v0")
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot read API: %w", err)
|
||||
}
|
||||
|
||||
ainfo, err := cliutil.GetAPIInfo(&cli.Context{}, repo.FullNode)
|
||||
if err != nil {
|
||||
return xerrors.Errorf(`could not get API info for FullNode: %w
|
||||
Set the environment variable to the value of "lotus auth api-info --perm=admin"`, err)
|
||||
}
|
||||
chainApiInfo := header.Get("Authorization")[7:] + ":" + ainfo.Addr
|
||||
_, err = guidedsetup.SaveConfigToLayer(minerRepoPath, layerName, overwrite, chainApiInfo)
|
||||
return err
|
||||
}
|
@ -12,9 +12,9 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
"github.com/filecoin-project/lotus/curiosrc/seal"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/provider/lpseal"
|
||||
)
|
||||
|
||||
var sealCmd = &cli.Command{
|
||||
@ -113,7 +113,7 @@ var sealStartCmd = &cli.Command{
|
||||
return xerrors.Errorf("getting seal proof type: %w", err)
|
||||
}
|
||||
|
||||
num, err := lpseal.AllocateSectorNumbers(ctx, dep.Full, dep.DB, act, cctx.Int("count"), func(tx *harmonydb.Tx, numbers []abi.SectorNumber) (bool, error) {
|
||||
num, err := seal.AllocateSectorNumbers(ctx, dep.Full, dep.DB, act, cctx.Int("count"), func(tx *harmonydb.Tx, numbers []abi.SectorNumber) (bool, error) {
|
||||
for _, n := range numbers {
|
||||
_, err := tx.Exec("insert into sectors_sdr_pipeline (sp_id, sector_number, reg_seal_proof) values ($1, $2, $3)", mid, n, spt)
|
||||
if err != nil {
|
@ -15,9 +15,9 @@ 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/cmd/curio/deps"
|
||||
curio "github.com/filecoin-project/lotus/curiosrc"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/provider"
|
||||
)
|
||||
|
||||
var testCmd = &cli.Command{
|
||||
@ -27,6 +27,9 @@ var testCmd = &cli.Command{
|
||||
//provingInfoCmd,
|
||||
wdPostCmd,
|
||||
},
|
||||
Before: func(cctx *cli.Context) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var wdPostCmd = &cli.Command{
|
||||
@ -47,7 +50,7 @@ var wdPostCmd = &cli.Command{
|
||||
var wdPostTaskCmd = &cli.Command{
|
||||
Name: "task",
|
||||
Aliases: []string{"scheduled", "schedule", "async", "asynchronous"},
|
||||
Usage: "Test the windowpost scheduler by running it on the next available lotus-provider. ",
|
||||
Usage: "Test the windowpost scheduler by running it on the next available curio. ",
|
||||
Flags: []cli.Flag{
|
||||
&cli.Uint64Flag{
|
||||
Name: "deadline",
|
||||
@ -148,7 +151,7 @@ It will not send any messages to the chain. Since it can compute any deadline, o
|
||||
&cli.StringFlag{
|
||||
Name: "storage-json",
|
||||
Usage: "path to json file containing storage config",
|
||||
Value: "~/.lotus-provider/storage.json",
|
||||
Value: "~/.curio/storage.json",
|
||||
},
|
||||
&cli.Uint64Flag{
|
||||
Name: "partition",
|
||||
@ -164,7 +167,8 @@ It will not send any messages to the chain. Since it can compute any deadline, o
|
||||
return err
|
||||
}
|
||||
|
||||
wdPostTask, wdPoStSubmitTask, derlareRecoverTask, err := provider.WindowPostScheduler(ctx, deps.Cfg.Fees, deps.Cfg.Proving, deps.Full, deps.Verif, deps.LW, nil, nil,
|
||||
wdPostTask, wdPoStSubmitTask, derlareRecoverTask, err := curio.WindowPostScheduler(
|
||||
ctx, deps.Cfg.Fees, deps.Cfg.Proving, deps.Full, deps.Verif, deps.LW, nil, nil,
|
||||
deps.As, deps.Maddrs, deps.DB, deps.Stor, deps.Si, deps.Cfg.Subsystems.WindowPostMaxTasks)
|
||||
if err != nil {
|
||||
return err
|
@ -27,34 +27,33 @@ import (
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/api/client"
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
"github.com/filecoin-project/lotus/curiosrc/market"
|
||||
"github.com/filecoin-project/lotus/curiosrc/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/node/repo"
|
||||
"github.com/filecoin-project/lotus/provider/lpmarket"
|
||||
"github.com/filecoin-project/lotus/provider/lpweb"
|
||||
"github.com/filecoin-project/lotus/storage/paths"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/fsutil"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
|
||||
var log = logging.Logger("lp/rpc")
|
||||
|
||||
var log = logging.Logger("curio/rpc")
|
||||
var permissioned = os.Getenv("LOTUS_DISABLE_AUTH_PERMISSIONED") != "1"
|
||||
|
||||
func LotusProviderHandler(
|
||||
func CurioHandler(
|
||||
authv func(ctx context.Context, token string) ([]auth.Permission, error),
|
||||
remote http.HandlerFunc,
|
||||
a api.LotusProvider,
|
||||
a api.Curio,
|
||||
permissioned bool) http.Handler {
|
||||
mux := mux.NewRouter()
|
||||
readerHandler, readerServerOpt := rpcenc.ReaderParamDecoder()
|
||||
rpcServer := jsonrpc.NewServer(jsonrpc.WithServerErrors(api.RPCErrors), readerServerOpt)
|
||||
|
||||
wapi := proxy.MetricedAPI[api.LotusProvider, api.LotusProviderStruct](a)
|
||||
wapi := proxy.MetricedAPI[api.Curio, api.CurioStruct](a)
|
||||
if permissioned {
|
||||
wapi = api.PermissionedAPI[api.LotusProvider, api.LotusProviderStruct](wapi)
|
||||
wapi = api.PermissionedAPI[api.Curio, api.CurioStruct](wapi)
|
||||
}
|
||||
|
||||
rpcServer.Register("Filecoin", wapi)
|
||||
@ -76,13 +75,16 @@ func LotusProviderHandler(
|
||||
return ah
|
||||
}
|
||||
|
||||
type ProviderAPI struct {
|
||||
type CurioAPI struct {
|
||||
*deps.Deps
|
||||
paths.SectorIndex
|
||||
ShutdownChan chan struct{}
|
||||
}
|
||||
|
||||
func (p *ProviderAPI) StorageDetachLocal(ctx context.Context, path string) error {
|
||||
func (p *CurioAPI) Version(context.Context) (api.Version, error) {
|
||||
return api.CurioAPIVersion0, nil
|
||||
}
|
||||
func (p *CurioAPI) StorageDetachLocal(ctx context.Context, path string) error {
|
||||
path, err := homedir.Expand(path)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("expanding local path: %w", err)
|
||||
@ -130,7 +132,7 @@ func (p *ProviderAPI) StorageDetachLocal(ctx context.Context, path string) error
|
||||
return p.LocalStore.ClosePath(ctx, localPath.ID)
|
||||
}
|
||||
|
||||
func (p *ProviderAPI) StorageLocal(ctx context.Context) (map[storiface.ID]string, error) {
|
||||
func (p *CurioAPI) StorageLocal(ctx context.Context) (map[storiface.ID]string, error) {
|
||||
ps, err := p.LocalStore.Local(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -144,27 +146,23 @@ func (p *ProviderAPI) StorageLocal(ctx context.Context) (map[storiface.ID]string
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (p *ProviderAPI) StorageStat(ctx context.Context, id storiface.ID) (fsutil.FsStat, error) {
|
||||
func (p *CurioAPI) StorageStat(ctx context.Context, id storiface.ID) (fsutil.FsStat, error) {
|
||||
return p.Stor.FsStat(ctx, id)
|
||||
}
|
||||
|
||||
func (p *ProviderAPI) Version(context.Context) (api.Version, error) {
|
||||
return api.ProviderAPIVersion0, nil
|
||||
}
|
||||
|
||||
func (p *ProviderAPI) AllocatePieceToSector(ctx context.Context, maddr address.Address, piece api.PieceDealInfo, rawSize int64, source url.URL, header http.Header) (api.SectorOffset, error) {
|
||||
di := lpmarket.NewPieceIngester(p.Deps.DB, p.Deps.Full)
|
||||
func (p *CurioAPI) AllocatePieceToSector(ctx context.Context, maddr address.Address, piece api.PieceDealInfo, rawSize int64, source url.URL, header http.Header) (api.SectorOffset, error) {
|
||||
di := market.NewPieceIngester(p.Deps.DB, p.Deps.Full)
|
||||
|
||||
return di.AllocatePieceToSector(ctx, maddr, piece, rawSize, source, header)
|
||||
}
|
||||
|
||||
// Trigger shutdown
|
||||
func (p *ProviderAPI) Shutdown(context.Context) error {
|
||||
func (p *CurioAPI) Shutdown(context.Context) error {
|
||||
close(p.ShutdownChan)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ProviderAPI) StorageAddLocal(ctx context.Context, path string) error {
|
||||
func (p *CurioAPI) StorageAddLocal(ctx context.Context, path string) error {
|
||||
path, err := homedir.Expand(path)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("expanding local path: %w", err)
|
||||
@ -212,10 +210,10 @@ func ListenAndServe(ctx context.Context, dependencies *deps.Deps, shutdownChan c
|
||||
}
|
||||
// Serve the RPC.
|
||||
srv := &http.Server{
|
||||
Handler: LotusProviderHandler(
|
||||
Handler: CurioHandler(
|
||||
authVerify,
|
||||
remoteHandler,
|
||||
&ProviderAPI{dependencies, dependencies.Si, shutdownChan},
|
||||
&CurioAPI{dependencies, dependencies.Si, shutdownChan},
|
||||
permissioned),
|
||||
ReadHeaderTimeout: time.Minute * 3,
|
||||
BaseContext: func(listener net.Listener) context.Context {
|
||||
@ -230,7 +228,7 @@ func ListenAndServe(ctx context.Context, dependencies *deps.Deps, shutdownChan c
|
||||
eg.Go(srv.ListenAndServe)
|
||||
|
||||
if dependencies.Cfg.Subsystems.EnableWebGui {
|
||||
web, err := lpweb.GetSrv(ctx, dependencies)
|
||||
web, err := web.GetSrv(ctx, dependencies)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -252,8 +250,8 @@ func ListenAndServe(ctx context.Context, dependencies *deps.Deps, shutdownChan c
|
||||
return eg.Wait()
|
||||
}
|
||||
|
||||
func GetProviderAPI(ctx *cli.Context) (api.LotusProvider, jsonrpc.ClientCloser, error) {
|
||||
addr, headers, err := cliutil.GetRawAPI(ctx, repo.Provider, "v0")
|
||||
func GetCurioAPI(ctx *cli.Context) (api.Curio, jsonrpc.ClientCloser, error) {
|
||||
addr, headers, err := cliutil.GetRawAPI(ctx, repo.Curio, "v0")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -272,5 +270,5 @@ func GetProviderAPI(ctx *cli.Context) (api.LotusProvider, jsonrpc.ClientCloser,
|
||||
|
||||
addr = u.String()
|
||||
|
||||
return client.NewProviderRpc(ctx.Context, addr, headers)
|
||||
return client.NewCurioRpc(ctx.Context, addr, headers)
|
||||
}
|
@ -14,9 +14,9 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"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/curio/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/rpc"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/tasks"
|
||||
"github.com/filecoin-project/lotus/lib/ulimit"
|
||||
"github.com/filecoin-project/lotus/metrics"
|
||||
"github.com/filecoin-project/lotus/node"
|
||||
@ -28,7 +28,7 @@ type stackTracer interface {
|
||||
|
||||
var runCmd = &cli.Command{
|
||||
Name: "run",
|
||||
Usage: "Start a lotus provider process",
|
||||
Usage: "Start a Curio process",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "listen",
|
||||
@ -53,12 +53,12 @@ var runCmd = &cli.Command{
|
||||
&cli.StringFlag{
|
||||
Name: "storage-json",
|
||||
Usage: "path to json file containing storage config",
|
||||
Value: "~/.lotus-provider/storage.json",
|
||||
Value: "~/.curio/storage.json",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "journal",
|
||||
Usage: "path to journal files",
|
||||
Value: "~/.lotus-provider/",
|
||||
Value: "~/.curio/",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "layers",
|
||||
@ -89,7 +89,7 @@ var runCmd = &cli.Command{
|
||||
ctx, _ := tag.New(lcli.DaemonContext(cctx),
|
||||
tag.Insert(metrics.Version, build.BuildVersion),
|
||||
tag.Insert(metrics.Commit, build.CurrentCommit),
|
||||
tag.Insert(metrics.NodeType, "provider"),
|
||||
tag.Insert(metrics.NodeType, "curio"),
|
||||
)
|
||||
shutdownChan := make(chan struct{})
|
||||
{
|
||||
@ -135,7 +135,7 @@ var runCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
finishCh := node.MonitorShutdown(shutdownChan) //node.ShutdownHandler{Component: "rpc server", StopFunc: rpcStopper},
|
||||
//node.ShutdownHandler{Component: "provider", StopFunc: stop},
|
||||
//node.ShutdownHandler{Component: "curio", StopFunc: stop},
|
||||
|
||||
<-finishCh
|
||||
return nil
|
||||
@ -144,8 +144,8 @@ var runCmd = &cli.Command{
|
||||
|
||||
var webCmd = &cli.Command{
|
||||
Name: "web",
|
||||
Usage: "Start lotus provider web interface",
|
||||
Description: `Start an instance of lotus provider web interface.
|
||||
Usage: "Start Curio web interface",
|
||||
Description: `Start an instance of Curio web interface.
|
||||
This creates the 'web' layer if it does not exist, then calls run with that layer.`,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
var stopCmd = &cli.Command{
|
||||
Name: "stop",
|
||||
Usage: "Stop a running lotus provider",
|
||||
Usage: "Stop a running Curio process",
|
||||
Flags: []cli.Flag{},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
api, closer, err := lcli.GetAPI(cctx)
|
@ -23,7 +23,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/rpc"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/rpc"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/fsutil"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
@ -104,7 +104,7 @@ over time
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
minerApi, closer, err := rpc.GetProviderAPI(cctx)
|
||||
minerApi, closer, err := rpc.GetCurioAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -182,7 +182,7 @@ var storageDetachCmd = &cli.Command{
|
||||
},
|
||||
ArgsUsage: "[path]",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
minerApi, closer, err := rpc.GetProviderAPI(cctx)
|
||||
minerApi, closer, err := rpc.GetCurioAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -213,7 +213,7 @@ var storageListCmd = &cli.Command{
|
||||
//storageListSectorsCmd,
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
minerApi, closer, err := rpc.GetProviderAPI(cctx)
|
||||
minerApi, closer, err := rpc.GetCurioAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -412,7 +412,7 @@ var storageFindCmd = &cli.Command{
|
||||
Usage: "find sector in the storage system",
|
||||
ArgsUsage: "[miner address] [sector number]",
|
||||
Action: func(cctx *cli.Context) error {
|
||||
minerApi, closer, err := rpc.GetProviderAPI(cctx)
|
||||
minerApi, closer, err := rpc.GetCurioAPI(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Package tasks contains tasks that can be run by the lotus-provider command.
|
||||
// Package tasks contains tasks that can be run by the curio command.
|
||||
package tasks
|
||||
|
||||
import (
|
||||
@ -8,18 +8,21 @@ import (
|
||||
"github.com/samber/lo"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
curio "github.com/filecoin-project/lotus/curiosrc"
|
||||
"github.com/filecoin-project/lotus/curiosrc/chainsched"
|
||||
"github.com/filecoin-project/lotus/curiosrc/ffi"
|
||||
"github.com/filecoin-project/lotus/curiosrc/message"
|
||||
"github.com/filecoin-project/lotus/curiosrc/piece"
|
||||
"github.com/filecoin-project/lotus/curiosrc/seal"
|
||||
"github.com/filecoin-project/lotus/curiosrc/winning"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/lib/lazy"
|
||||
"github.com/filecoin-project/lotus/lib/must"
|
||||
"github.com/filecoin-project/lotus/node/modules"
|
||||
"github.com/filecoin-project/lotus/provider"
|
||||
"github.com/filecoin-project/lotus/provider/chainsched"
|
||||
"github.com/filecoin-project/lotus/provider/lpffi"
|
||||
"github.com/filecoin-project/lotus/provider/lpmessage"
|
||||
"github.com/filecoin-project/lotus/provider/lpseal"
|
||||
"github.com/filecoin-project/lotus/provider/lpwinning"
|
||||
)
|
||||
|
||||
var log = logging.Logger("lotus-provider/deps")
|
||||
var log = logging.Logger("curio/deps")
|
||||
|
||||
func StartTasks(ctx context.Context, dependencies *deps.Deps) (*harmonytask.TaskEngine, error) {
|
||||
cfg := dependencies.Cfg
|
||||
@ -34,7 +37,7 @@ func StartTasks(ctx context.Context, dependencies *deps.Deps) (*harmonytask.Task
|
||||
si := dependencies.Si
|
||||
var activeTasks []harmonytask.TaskInterface
|
||||
|
||||
sender, sendTask := lpmessage.NewSender(full, full, db)
|
||||
sender, sendTask := message.NewSender(full, full, db)
|
||||
activeTasks = append(activeTasks, sendTask)
|
||||
|
||||
chainSched := chainsched.New(full)
|
||||
@ -48,8 +51,10 @@ func StartTasks(ctx context.Context, dependencies *deps.Deps) (*harmonytask.Task
|
||||
// PoSt
|
||||
|
||||
if cfg.Subsystems.EnableWindowPost {
|
||||
wdPostTask, wdPoStSubmitTask, derlareRecoverTask, err := provider.WindowPostScheduler(ctx, cfg.Fees, cfg.Proving, full, verif, lw, sender,
|
||||
chainSched, as, maddrs, db, stor, si, cfg.Subsystems.WindowPostMaxTasks)
|
||||
wdPostTask, wdPoStSubmitTask, derlareRecoverTask, err := curio.WindowPostScheduler(
|
||||
ctx, cfg.Fees, cfg.Proving, full, verif, lw, sender, chainSched,
|
||||
as, maddrs, db, stor, si, cfg.Subsystems.WindowPostMaxTasks)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -58,12 +63,25 @@ func StartTasks(ctx context.Context, dependencies *deps.Deps) (*harmonytask.Task
|
||||
}
|
||||
|
||||
if cfg.Subsystems.EnableWinningPost {
|
||||
winPoStTask := lpwinning.NewWinPostTask(cfg.Subsystems.WinningPostMaxTasks, db, lw, verif, full, maddrs)
|
||||
winPoStTask := winning.NewWinPostTask(cfg.Subsystems.WinningPostMaxTasks, db, lw, verif, full, maddrs)
|
||||
activeTasks = append(activeTasks, winPoStTask)
|
||||
needProofParams = true
|
||||
}
|
||||
}
|
||||
|
||||
slrLazy := lazy.MakeLazy(func() (*ffi.SealCalls, error) {
|
||||
return ffi.NewSealCalls(stor, lstor, si), nil
|
||||
})
|
||||
|
||||
{
|
||||
// Piece handling
|
||||
if cfg.Subsystems.EnableParkPiece {
|
||||
parkPieceTask := piece.NewParkPieceTask(db, must.One(slrLazy.Val()), cfg.Subsystems.ParkPieceMaxTasks)
|
||||
cleanupPieceTask := piece.NewCleanupPieceTask(db, must.One(slrLazy.Val()), 0)
|
||||
activeTasks = append(activeTasks, parkPieceTask, cleanupPieceTask)
|
||||
}
|
||||
}
|
||||
|
||||
hasAnySealingTask := cfg.Subsystems.EnableSealSDR ||
|
||||
cfg.Subsystems.EnableSealSDRTrees ||
|
||||
cfg.Subsystems.EnableSendPrecommitMsg ||
|
||||
@ -73,40 +91,40 @@ func StartTasks(ctx context.Context, dependencies *deps.Deps) (*harmonytask.Task
|
||||
{
|
||||
// Sealing
|
||||
|
||||
var sp *lpseal.SealPoller
|
||||
var slr *lpffi.SealCalls
|
||||
var sp *seal.SealPoller
|
||||
var slr *ffi.SealCalls
|
||||
if hasAnySealingTask {
|
||||
sp = lpseal.NewPoller(db, full)
|
||||
sp = seal.NewPoller(db, full)
|
||||
go sp.RunPoller(ctx)
|
||||
|
||||
slr = lpffi.NewSealCalls(stor, lstor, si)
|
||||
slr = must.One(slrLazy.Val())
|
||||
}
|
||||
|
||||
// NOTE: Tasks with the LEAST priority are at the top
|
||||
if cfg.Subsystems.EnableSealSDR {
|
||||
sdrTask := lpseal.NewSDRTask(full, db, sp, slr, cfg.Subsystems.SealSDRMaxTasks)
|
||||
sdrTask := seal.NewSDRTask(full, db, sp, slr, cfg.Subsystems.SealSDRMaxTasks)
|
||||
activeTasks = append(activeTasks, sdrTask)
|
||||
}
|
||||
if cfg.Subsystems.EnableSealSDRTrees {
|
||||
treesTask := lpseal.NewTreesTask(sp, db, slr, cfg.Subsystems.SealSDRTreesMaxTasks)
|
||||
finalizeTask := lpseal.NewFinalizeTask(cfg.Subsystems.FinalizeMaxTasks, sp, slr, db)
|
||||
treesTask := seal.NewTreesTask(sp, db, slr, cfg.Subsystems.SealSDRTreesMaxTasks)
|
||||
finalizeTask := seal.NewFinalizeTask(cfg.Subsystems.FinalizeMaxTasks, sp, slr, db)
|
||||
activeTasks = append(activeTasks, treesTask, finalizeTask)
|
||||
}
|
||||
if cfg.Subsystems.EnableSendPrecommitMsg {
|
||||
precommitTask := lpseal.NewSubmitPrecommitTask(sp, db, full, sender, as, cfg.Fees.MaxPreCommitGasFee)
|
||||
precommitTask := seal.NewSubmitPrecommitTask(sp, db, full, sender, as, cfg.Fees.MaxPreCommitGasFee)
|
||||
activeTasks = append(activeTasks, precommitTask)
|
||||
}
|
||||
if cfg.Subsystems.EnablePoRepProof {
|
||||
porepTask := lpseal.NewPoRepTask(db, full, sp, slr, cfg.Subsystems.PoRepProofMaxTasks)
|
||||
porepTask := seal.NewPoRepTask(db, full, sp, slr, cfg.Subsystems.PoRepProofMaxTasks)
|
||||
activeTasks = append(activeTasks, porepTask)
|
||||
needProofParams = true
|
||||
}
|
||||
if cfg.Subsystems.EnableMoveStorage {
|
||||
moveStorageTask := lpseal.NewMoveStorageTask(sp, slr, db, cfg.Subsystems.MoveStorageMaxTasks)
|
||||
moveStorageTask := seal.NewMoveStorageTask(sp, slr, db, cfg.Subsystems.MoveStorageMaxTasks)
|
||||
activeTasks = append(activeTasks, moveStorageTask)
|
||||
}
|
||||
if cfg.Subsystems.EnableSendCommitMsg {
|
||||
commitTask := lpseal.NewSubmitCommitTask(sp, db, full, sender, as, cfg.Fees.MaxCommitGasFee)
|
||||
commitTask := seal.NewSubmitCommitTask(sp, db, full, sender, as, cfg.Fees.MaxCommitGasFee)
|
||||
activeTasks = append(activeTasks, commitTask)
|
||||
}
|
||||
}
|
||||
@ -134,7 +152,7 @@ func StartTasks(ctx context.Context, dependencies *deps.Deps) (*harmonytask.Task
|
||||
}
|
||||
|
||||
if hasAnySealingTask {
|
||||
watcher, err := lpmessage.NewMessageWatcher(db, ht, chainSched, full)
|
||||
watcher, err := message.NewMessageWatcher(db, ht, chainSched, full)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
@ -1,254 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/fatih/color"
|
||||
"github.com/ipfs/go-datastore"
|
||||
"github.com/samber/lo"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/deps"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
"github.com/filecoin-project/lotus/node/modules"
|
||||
"github.com/filecoin-project/lotus/node/repo"
|
||||
)
|
||||
|
||||
var configMigrateCmd = &cli.Command{
|
||||
Name: "from-miner",
|
||||
Usage: "Express a database config (for lotus-provider) from an existing miner.",
|
||||
Description: "Express a database config (for lotus-provider) from an existing miner.",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: FlagMinerRepo,
|
||||
Aliases: []string{FlagMinerRepoDeprecation},
|
||||
EnvVars: []string{"LOTUS_MINER_PATH", "LOTUS_STORAGE_PATH"},
|
||||
Value: "~/.lotusminer",
|
||||
Usage: "Miner repo path",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "repo",
|
||||
EnvVars: []string{"LOTUS_PATH"},
|
||||
Hidden: true,
|
||||
Value: "~/.lotus",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "to-layer",
|
||||
Aliases: []string{"t"},
|
||||
Usage: "The layer name for this data push. 'base' is recommended for single-miner setup.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "overwrite",
|
||||
Aliases: []string{"o"},
|
||||
Usage: "Use this with --to-layer to replace an existing layer",
|
||||
},
|
||||
},
|
||||
Action: fromMiner,
|
||||
}
|
||||
|
||||
const (
|
||||
FlagMinerRepo = "miner-repo"
|
||||
)
|
||||
|
||||
const FlagMinerRepoDeprecation = "storagerepo"
|
||||
|
||||
func fromMiner(cctx *cli.Context) (err error) {
|
||||
ctx := context.Background()
|
||||
cliCommandColor := color.New(color.FgHiBlue).SprintFunc()
|
||||
configColor := color.New(color.FgHiGreen).SprintFunc()
|
||||
|
||||
r, err := repo.NewFS(cctx.String(FlagMinerRepo))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ok, err := r.Exists()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("repo not initialized")
|
||||
}
|
||||
|
||||
lr, err := r.LockRO(repo.StorageMiner)
|
||||
if err != nil {
|
||||
return fmt.Errorf("locking repo: %w", err)
|
||||
}
|
||||
defer func() { _ = lr.Close() }()
|
||||
|
||||
cfgNode, err := lr.Config()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting node config: %w", err)
|
||||
}
|
||||
smCfg := cfgNode.(*config.StorageMiner)
|
||||
|
||||
db, err := harmonydb.NewFromConfig(smCfg.HarmonyDB)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not reach the database. Ensure the Miner config toml's HarmonyDB entry"+
|
||||
" is setup to reach Yugabyte correctly: %w", err)
|
||||
}
|
||||
|
||||
var titles []string
|
||||
err = db.Select(ctx, &titles, `SELECT title FROM harmony_config WHERE LENGTH(config) > 0`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("miner cannot reach the db. Ensure the config toml's HarmonyDB entry"+
|
||||
" is setup to reach Yugabyte correctly: %s", err.Error())
|
||||
}
|
||||
name := cctx.String("to-layer")
|
||||
if name == "" {
|
||||
name = fmt.Sprintf("mig%d", len(titles))
|
||||
} else {
|
||||
if lo.Contains(titles, name) && !cctx.Bool("overwrite") {
|
||||
return errors.New("the overwrite flag is needed to replace existing layer: " + name)
|
||||
}
|
||||
}
|
||||
msg := "Layer " + configColor(name) + ` created. `
|
||||
|
||||
// Copy over identical settings:
|
||||
|
||||
buf, err := os.ReadFile(path.Join(lr.Path(), "config.toml"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read config.toml: %w", err)
|
||||
}
|
||||
lpCfg := config.DefaultLotusProvider()
|
||||
_, err = deps.LoadConfigWithUpgrades(string(buf), lpCfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not decode toml: %w", err)
|
||||
}
|
||||
|
||||
// Populate Miner Address
|
||||
mmeta, err := lr.Datastore(ctx, "/metadata")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("opening miner metadata datastore: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = mmeta.Close()
|
||||
}()
|
||||
|
||||
maddrBytes, err := mmeta.Get(ctx, datastore.NewKey("miner-address"))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting miner address datastore entry: %w", err)
|
||||
}
|
||||
|
||||
addr, err := address.NewFromBytes(maddrBytes)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parsing miner actor address: %w", err)
|
||||
}
|
||||
|
||||
lpCfg.Addresses = []config.LotusProviderAddresses{{
|
||||
MinerAddresses: []string{addr.String()},
|
||||
}}
|
||||
|
||||
ks, err := lr.KeyStore()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("keystore err: %w", err)
|
||||
}
|
||||
js, err := ks.Get(modules.JWTSecretName)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("error getting JWTSecretName: %w", err)
|
||||
}
|
||||
|
||||
lpCfg.Apis.StorageRPCSecret = base64.StdEncoding.EncodeToString(js.PrivateKey)
|
||||
|
||||
// Populate API Key
|
||||
_, header, err := cliutil.GetRawAPI(cctx, repo.FullNode, "v0")
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot read API: %w", err)
|
||||
}
|
||||
|
||||
ainfo, err := cliutil.GetAPIInfo(&cli.Context{}, repo.FullNode)
|
||||
if err != nil {
|
||||
return xerrors.Errorf(`could not get API info for FullNode: %w
|
||||
Set the environment variable to the value of "lotus auth api-info --perm=admin"`, err)
|
||||
}
|
||||
lpCfg.Apis.ChainApiInfo = []string{header.Get("Authorization")[7:] + ":" + ainfo.Addr}
|
||||
|
||||
// WindowPoSt message
|
||||
msg += "\n!! Before running lotus-provider with Window PoSt enabled, ensure any miner/worker answering of WindowPost is disabled by " +
|
||||
"(on Miner) " + configColor("DisableBuiltinWindowPoSt=true") + " and (on Workers) not enabling windowpost on CLI or via " +
|
||||
"environment variable " + configColor("LOTUS_WORKER_WINDOWPOST") + "."
|
||||
|
||||
// WinningPoSt message
|
||||
msg += "\n!! Before running lotus-provider with Winning PoSt enabled, ensure any miner/worker answering of WinningPost is disabled by " +
|
||||
"(on Miner) " + configColor("DisableBuiltinWinningPoSt=true") + " and (on Workers) not enabling winningpost on CLI or via " +
|
||||
"environment variable " + configColor("LOTUS_WORKER_WINNINGPOST") + "."
|
||||
|
||||
// Express as configTOML
|
||||
configTOML := &bytes.Buffer{}
|
||||
if err = toml.NewEncoder(configTOML).Encode(lpCfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !lo.Contains(titles, "base") {
|
||||
cfg, err := getDefaultConfig(true)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("Cannot get default config: %w", err)
|
||||
}
|
||||
_, err = db.Exec(ctx, "INSERT INTO harmony_config (title, config) VALUES ('base', $1)", cfg)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if cctx.Bool("overwrite") {
|
||||
i, err := db.Exec(ctx, "DELETE FROM harmony_config WHERE title=$1", name)
|
||||
if i != 0 {
|
||||
fmt.Println("Overwriting existing layer")
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("Got error while deleting existing layer: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
_, err = db.Exec(ctx, "INSERT INTO harmony_config (title, config) VALUES ($1, $2)", name, configTOML.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dbSettings := ""
|
||||
def := config.DefaultStorageMiner().HarmonyDB
|
||||
if def.Hosts[0] != smCfg.HarmonyDB.Hosts[0] {
|
||||
dbSettings += ` --db-host="` + strings.Join(smCfg.HarmonyDB.Hosts, ",") + `"`
|
||||
}
|
||||
if def.Port != smCfg.HarmonyDB.Port {
|
||||
dbSettings += " --db-port=" + smCfg.HarmonyDB.Port
|
||||
}
|
||||
if def.Username != smCfg.HarmonyDB.Username {
|
||||
dbSettings += ` --db-user="` + smCfg.HarmonyDB.Username + `"`
|
||||
}
|
||||
if def.Password != smCfg.HarmonyDB.Password {
|
||||
dbSettings += ` --db-password="` + smCfg.HarmonyDB.Password + `"`
|
||||
}
|
||||
if def.Database != smCfg.HarmonyDB.Database {
|
||||
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 `+layerMaybe)
|
||||
fmt.Println(msg)
|
||||
return nil
|
||||
}
|
@ -14,7 +14,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
manet "github.com/multiformats/go-multiaddr/net"
|
||||
"github.com/urfave/cli/v2"
|
||||
@ -34,13 +35,14 @@ import (
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
lcli "github.com/filecoin-project/lotus/cli"
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
cumarket "github.com/filecoin-project/lotus/curiosrc/market"
|
||||
"github.com/filecoin-project/lotus/curiosrc/market/fakelm"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/must"
|
||||
"github.com/filecoin-project/lotus/lib/nullreader"
|
||||
"github.com/filecoin-project/lotus/metrics/proxy"
|
||||
"github.com/filecoin-project/lotus/node"
|
||||
"github.com/filecoin-project/lotus/provider/lpmarket"
|
||||
"github.com/filecoin-project/lotus/provider/lpmarket/fakelm"
|
||||
"github.com/filecoin-project/lotus/storage/paths"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
@ -88,7 +90,7 @@ var lpUtilStartDealCmd = &cli.Command{
|
||||
}
|
||||
|
||||
// open rpc
|
||||
var rpc api.LotusProviderStruct
|
||||
var rpc api.CurioStruct
|
||||
closer2, err := jsonrpc.NewMergeClient(ctx, cctx.String("provider-rpc"), "Filecoin", []interface{}{&rpc.Internal}, nil)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("open rpc: %w", err)
|
||||
@ -368,7 +370,7 @@ var lpBoostProxyCmd = &cli.Command{
|
||||
|
||||
defer closer()
|
||||
|
||||
pin := lpmarket.NewPieceIngester(db, full)
|
||||
pin := cumarket.NewPieceIngester(db, full)
|
||||
|
||||
si := paths.NewDBIndex(nil, db)
|
||||
|
||||
@ -427,7 +429,7 @@ var lpBoostProxyCmd = &cli.Command{
|
||||
}
|
||||
|
||||
pieceInfoLk := new(sync.Mutex)
|
||||
pieceInfos := map[cid.Cid][]pieceInfo{}
|
||||
pieceInfos := map[uuid.UUID][]pieceInfo{}
|
||||
|
||||
ast.Internal.SectorAddPieceToAny = func(ctx context.Context, pieceSize abi.UnpaddedPieceSize, pieceData storiface.Data, deal api.PieceDealInfo) (api.SectorOffset, error) {
|
||||
origPieceData := pieceData
|
||||
@ -449,25 +451,103 @@ var lpBoostProxyCmd = &cli.Command{
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
pieceUUID := uuid.New()
|
||||
|
||||
color.Blue("%s %s piece assign request with id %s", deal.DealProposal.PieceCID, deal.DealProposal.Provider, pieceUUID)
|
||||
|
||||
pieceInfoLk.Lock()
|
||||
pieceInfos[deal.DealProposal.PieceCID] = append(pieceInfos[deal.DealProposal.PieceCID], pi)
|
||||
pieceInfos[pieceUUID] = append(pieceInfos[pieceUUID], pi)
|
||||
pieceInfoLk.Unlock()
|
||||
|
||||
// /piece?piece_cid=xxxx
|
||||
dataUrl := rootUrl
|
||||
dataUrl.Path = "/piece"
|
||||
dataUrl.RawQuery = "piece_cid=" + deal.DealProposal.PieceCID.String()
|
||||
dataUrl.RawQuery = "piece_id=" + pieceUUID.String()
|
||||
|
||||
// add piece entry
|
||||
|
||||
var refID int64
|
||||
var pieceWasCreated bool
|
||||
|
||||
comm, err := db.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) {
|
||||
var pieceID int64
|
||||
// Attempt to select the piece ID first
|
||||
err = tx.QueryRow(`SELECT id FROM parked_pieces WHERE piece_cid = $1`, deal.DealProposal.PieceCID.String()).Scan(&pieceID)
|
||||
|
||||
if err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
// Piece does not exist, attempt to insert
|
||||
err = tx.QueryRow(`
|
||||
INSERT INTO parked_pieces (piece_cid, piece_padded_size, piece_raw_size)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (piece_cid) DO NOTHING
|
||||
RETURNING id`, deal.DealProposal.PieceCID.String(), int64(pieceSize.Padded()), int64(pieceSize)).Scan(&pieceID)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("inserting new parked piece and getting id: %w", err)
|
||||
}
|
||||
pieceWasCreated = true // New piece was created
|
||||
} else {
|
||||
// Some other error occurred during select
|
||||
return false, xerrors.Errorf("checking existing parked piece: %w", err)
|
||||
}
|
||||
} else {
|
||||
pieceWasCreated = false // Piece already exists, no new piece was created
|
||||
}
|
||||
|
||||
// Add parked_piece_ref
|
||||
err = tx.QueryRow(`INSERT INTO parked_piece_refs (piece_id, data_url)
|
||||
VALUES ($1, $2) RETURNING ref_id`, pieceID, dataUrl.String()).Scan(&refID)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("inserting parked piece ref: %w", err)
|
||||
}
|
||||
|
||||
// If everything went well, commit the transaction
|
||||
return true, nil // This will commit the transaction
|
||||
}, harmonydb.OptionRetry())
|
||||
if err != nil {
|
||||
return api.SectorOffset{}, xerrors.Errorf("inserting parked piece: %w", err)
|
||||
}
|
||||
if !comm {
|
||||
return api.SectorOffset{}, xerrors.Errorf("piece tx didn't commit")
|
||||
}
|
||||
|
||||
// wait for piece to be parked
|
||||
if pieceWasCreated {
|
||||
<-pi.done
|
||||
} else {
|
||||
// If the piece was not created, we need to close the done channel
|
||||
close(pi.done)
|
||||
|
||||
go func() {
|
||||
// close the data reader (drain to eof if it's not a closer)
|
||||
if closer, ok := pieceData.(io.Closer); ok {
|
||||
if err := closer.Close(); err != nil {
|
||||
log.Warnw("closing pieceData in DataCid", "error", err)
|
||||
}
|
||||
} else {
|
||||
log.Warnw("pieceData is not an io.Closer", "type", fmt.Sprintf("%T", pieceData))
|
||||
|
||||
_, err := io.Copy(io.Discard, pieceData)
|
||||
if err != nil {
|
||||
log.Warnw("draining pieceData in DataCid", "error", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
pieceIDUrl := url.URL{
|
||||
Scheme: "pieceref",
|
||||
Opaque: fmt.Sprintf("%d", refID),
|
||||
}
|
||||
|
||||
// make a sector
|
||||
so, err := pin.AllocatePieceToSector(ctx, maddr, deal, int64(pieceSize), dataUrl, nil)
|
||||
so, err := pin.AllocatePieceToSector(ctx, maddr, deal, int64(pieceSize), pieceIDUrl, nil)
|
||||
if err != nil {
|
||||
return api.SectorOffset{}, err
|
||||
}
|
||||
|
||||
color.Blue("%s piece assigned to sector f0%d:%d @ %d", deal.DealProposal.PieceCID, mid, so.Sector, so.Offset)
|
||||
|
||||
<-pi.done
|
||||
|
||||
return so, nil
|
||||
}
|
||||
|
||||
@ -484,10 +564,12 @@ var lpBoostProxyCmd = &cli.Command{
|
||||
ast.Internal.StorageGetLocks = si.StorageGetLocks
|
||||
|
||||
var pieceHandler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
|
||||
// /piece?piece_cid=xxxx
|
||||
pieceCid, err := cid.Decode(r.URL.Query().Get("piece_cid"))
|
||||
// /piece?piece_id=xxxx
|
||||
pieceUUID := r.URL.Query().Get("piece_id")
|
||||
|
||||
pu, err := uuid.Parse(pieceUUID)
|
||||
if err != nil {
|
||||
http.Error(w, "bad piece_cid", http.StatusBadRequest)
|
||||
http.Error(w, "bad piece id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -496,13 +578,13 @@ var lpBoostProxyCmd = &cli.Command{
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("%s request for piece from %s\n", pieceCid, r.RemoteAddr)
|
||||
fmt.Printf("%s request for piece from %s\n", pieceUUID, r.RemoteAddr)
|
||||
|
||||
pieceInfoLk.Lock()
|
||||
pis, ok := pieceInfos[pieceCid]
|
||||
pis, ok := pieceInfos[pu]
|
||||
if !ok {
|
||||
http.Error(w, "piece not found", http.StatusNotFound)
|
||||
color.Red("%s not found", pieceCid)
|
||||
color.Red("%s not found", pu)
|
||||
pieceInfoLk.Unlock()
|
||||
return
|
||||
}
|
||||
@ -511,7 +593,10 @@ var lpBoostProxyCmd = &cli.Command{
|
||||
pi := pis[0]
|
||||
pis = pis[1:]
|
||||
|
||||
pieceInfos[pieceCid] = pis
|
||||
pieceInfos[pu] = pis
|
||||
if len(pis) == 0 {
|
||||
delete(pieceInfos, pu)
|
||||
}
|
||||
|
||||
pieceInfoLk.Unlock()
|
||||
|
||||
@ -533,7 +618,7 @@ var lpBoostProxyCmd = &cli.Command{
|
||||
return
|
||||
}
|
||||
|
||||
color.Green("%s served %.3f MiB in %s (%.2f MiB/s)", pieceCid, float64(n)/(1024*1024), took, mbps)
|
||||
color.Green("%s served %.3f MiB in %s (%.2f MiB/s)", pu, float64(n)/(1024*1024), took, mbps)
|
||||
}
|
||||
|
||||
finalApi := proxy.LoggingAPI[api.StorageMiner, api.StorageMinerStruct](&ast)
|
@ -72,7 +72,7 @@ var backfillEventsCmd = &cli.Command{
|
||||
}
|
||||
if cctx.IsSet("from") {
|
||||
// we need to fetch the tipset after the epoch being specified since we will need to advance currTs
|
||||
currTs, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Int("from")+1), currTs.Key())
|
||||
currTs, err = api.ChainGetTipSetAfterHeight(ctx, abi.ChainEpoch(cctx.Int("from")+1), currTs.Key())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ func (sim *Simulation) saveConfig() error {
|
||||
|
||||
var simulationPrefix = datastore.NewKey("/simulation")
|
||||
|
||||
// key returns the the key in the form /simulation/<subkey>/<simulation-name>. For example,
|
||||
// key returns the key in the form /simulation/<subkey>/<simulation-name>. For example,
|
||||
// /simulation/head/default.
|
||||
func (sim *Simulation) key(subkey string) datastore.Key {
|
||||
return simulationPrefix.ChildString(subkey).ChildString(sim.name)
|
||||
|
@ -100,7 +100,7 @@ type ExecuteTipsetParams struct {
|
||||
// ExecuteTipset executes the supplied tipset on top of the state represented
|
||||
// by the preroot CID.
|
||||
//
|
||||
// This method returns the the receipts root, the poststate root, and the VM
|
||||
// This method returns the receipts root, the poststate root, and the VM
|
||||
// message results. The latter _include_ implicit messages, such as cron ticks
|
||||
// and reward withdrawal per miner.
|
||||
func (d *Driver) ExecuteTipset(bs blockstore.Blockstore, ds ds.Batching, params ExecuteTipsetParams) (*ExecuteTipsetResult, error) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package provider
|
||||
package curio
|
||||
|
||||
import (
|
||||
"golang.org/x/xerrors"
|
||||
@ -6,11 +6,11 @@ import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/curiosrc/multictladdr"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
"github.com/filecoin-project/lotus/provider/multictladdr"
|
||||
)
|
||||
|
||||
func AddressSelector(addrConf []config.LotusProviderAddresses) func() (*multictladdr.MultiAddressSelector, error) {
|
||||
func AddressSelector(addrConf []config.CurioAddresses) func() (*multictladdr.MultiAddressSelector, error) {
|
||||
return func() (*multictladdr.MultiAddressSelector, error) {
|
||||
as := &multictladdr.MultiAddressSelector{
|
||||
MinerMap: make(map[address.Address]api.AddressConfig),
|
46
curiosrc/builder.go
Normal file
46
curiosrc/builder.go
Normal file
@ -0,0 +1,46 @@
|
||||
package curio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/curiosrc/chainsched"
|
||||
"github.com/filecoin-project/lotus/curiosrc/message"
|
||||
"github.com/filecoin-project/lotus/curiosrc/multictladdr"
|
||||
"github.com/filecoin-project/lotus/curiosrc/window"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
dtypes "github.com/filecoin-project/lotus/node/modules/dtypes"
|
||||
"github.com/filecoin-project/lotus/storage/paths"
|
||||
"github.com/filecoin-project/lotus/storage/sealer"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
|
||||
//var log = logging.Logger("provider")
|
||||
|
||||
func WindowPostScheduler(ctx context.Context, fc config.CurioFees, pc config.ProvingConfig,
|
||||
api api.FullNode, verif storiface.Verifier, lw *sealer.LocalWorker, sender *message.Sender, chainSched *chainsched.CurioChainSched,
|
||||
as *multictladdr.MultiAddressSelector, addresses map[dtypes.MinerAddress]bool, db *harmonydb.DB,
|
||||
stor paths.Store, idx paths.SectorIndex, max int) (*window.WdPostTask, *window.WdPostSubmitTask, *window.WdPostRecoverDeclareTask, error) {
|
||||
|
||||
// todo config
|
||||
ft := window.NewSimpleFaultTracker(stor, idx, pc.ParallelCheckLimit, time.Duration(pc.SingleCheckTimeout), time.Duration(pc.PartitionCheckTimeout))
|
||||
|
||||
computeTask, err := window.NewWdPostTask(db, api, ft, lw, verif, chainSched, addresses, max)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
submitTask, err := window.NewWdPostSubmitTask(chainSched, sender, db, api, fc.MaxWindowPoStGasFee, as)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
recoverTask, err := window.NewWdPostRecoverDeclareTask(sender, db, api, ft, as, chainSched, fc.MaxWindowPoStGasFee, addresses)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return computeTask, submitTask, recoverTask, nil
|
||||
}
|
@ -14,29 +14,29 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
var log = logging.Logger("chainsched")
|
||||
var log = logging.Logger("curio/chainsched")
|
||||
|
||||
type NodeAPI interface {
|
||||
ChainHead(context.Context) (*types.TipSet, error)
|
||||
ChainNotify(context.Context) (<-chan []*api.HeadChange, error)
|
||||
}
|
||||
|
||||
type ProviderChainSched struct {
|
||||
type CurioChainSched struct {
|
||||
api NodeAPI
|
||||
|
||||
callbacks []UpdateFunc
|
||||
started bool
|
||||
}
|
||||
|
||||
func New(api NodeAPI) *ProviderChainSched {
|
||||
return &ProviderChainSched{
|
||||
func New(api NodeAPI) *CurioChainSched {
|
||||
return &CurioChainSched{
|
||||
api: api,
|
||||
}
|
||||
}
|
||||
|
||||
type UpdateFunc func(ctx context.Context, revert, apply *types.TipSet) error
|
||||
|
||||
func (s *ProviderChainSched) AddHandler(ch UpdateFunc) error {
|
||||
func (s *CurioChainSched) AddHandler(ch UpdateFunc) error {
|
||||
if s.started {
|
||||
return xerrors.Errorf("cannot add handler after start")
|
||||
}
|
||||
@ -45,7 +45,7 @@ func (s *ProviderChainSched) AddHandler(ch UpdateFunc) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ProviderChainSched) Run(ctx context.Context) {
|
||||
func (s *CurioChainSched) Run(ctx context.Context) {
|
||||
s.started = true
|
||||
|
||||
var (
|
||||
@ -88,7 +88,7 @@ func (s *ProviderChainSched) Run(ctx context.Context) {
|
||||
continue
|
||||
}
|
||||
|
||||
ctx, span := trace.StartSpan(ctx, "ProviderChainSched.headChange")
|
||||
ctx, span := trace.StartSpan(ctx, "CurioChainSched.headChange")
|
||||
|
||||
s.update(ctx, nil, chg.Val)
|
||||
|
||||
@ -97,7 +97,7 @@ func (s *ProviderChainSched) Run(ctx context.Context) {
|
||||
continue
|
||||
}
|
||||
|
||||
ctx, span := trace.StartSpan(ctx, "ProviderChainSched.headChange")
|
||||
ctx, span := trace.StartSpan(ctx, "CurioChainSched.headChange")
|
||||
|
||||
var lowest, highest *types.TipSet = nil, nil
|
||||
|
||||
@ -122,15 +122,15 @@ func (s *ProviderChainSched) Run(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ProviderChainSched) update(ctx context.Context, revert, apply *types.TipSet) {
|
||||
func (s *CurioChainSched) update(ctx context.Context, revert, apply *types.TipSet) {
|
||||
if apply == nil {
|
||||
log.Error("no new tipset in ProviderChainSched.update")
|
||||
log.Error("no new tipset in CurioChainSched.update")
|
||||
return
|
||||
}
|
||||
|
||||
for _, ch := range s.callbacks {
|
||||
if err := ch(ctx, revert, apply); err != nil {
|
||||
log.Errorf("handling head updates in provider chain sched: %+v", err)
|
||||
log.Errorf("handling head updates in curio chain sched: %+v", err)
|
||||
}
|
||||
}
|
||||
}
|
75
curiosrc/ffi/piece_funcs.go
Normal file
75
curiosrc/ffi/piece_funcs.go
Normal file
@ -0,0 +1,75 @@
|
||||
package ffi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
|
||||
func (sb *SealCalls) WritePiece(ctx context.Context, pieceID storiface.PieceNumber, size int64, data io.Reader) error {
|
||||
// todo: config(?): allow setting PathStorage for this
|
||||
// todo storage reservations
|
||||
paths, done, err := sb.sectors.AcquireSector(ctx, nil, pieceID.Ref(), storiface.FTNone, storiface.FTPiece, storiface.PathSealing)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer done()
|
||||
|
||||
dest := paths.Piece
|
||||
tempDest := dest + ".tmp"
|
||||
|
||||
destFile, err := os.OpenFile(tempDest, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("creating temp piece file '%s': %w", tempDest, err)
|
||||
}
|
||||
|
||||
removeTemp := true
|
||||
defer func() {
|
||||
if removeTemp {
|
||||
rerr := os.Remove(tempDest)
|
||||
if rerr != nil {
|
||||
log.Errorf("removing temp file: %+v", rerr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
copyStart := time.Now()
|
||||
|
||||
n, err := io.CopyBuffer(destFile, io.LimitReader(data, size), make([]byte, 8<<20))
|
||||
if err != nil {
|
||||
_ = destFile.Close()
|
||||
return xerrors.Errorf("copying piece data: %w", err)
|
||||
}
|
||||
|
||||
if err := destFile.Close(); err != nil {
|
||||
return xerrors.Errorf("closing temp piece file: %w", err)
|
||||
}
|
||||
|
||||
if n != size {
|
||||
return xerrors.Errorf("short write: %d", n)
|
||||
}
|
||||
|
||||
copyEnd := time.Now()
|
||||
|
||||
log.Infow("wrote parked piece", "piece", pieceID, "size", size, "duration", copyEnd.Sub(copyStart), "dest", dest, "MiB/s", float64(size)/(1<<20)/copyEnd.Sub(copyStart).Seconds())
|
||||
|
||||
if err := os.Rename(tempDest, dest); err != nil {
|
||||
return xerrors.Errorf("rename temp piece to dest %s -> %s: %w", tempDest, dest, err)
|
||||
}
|
||||
|
||||
removeTemp = false
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sb *SealCalls) PieceReader(ctx context.Context, id storiface.PieceNumber) (io.ReadCloser, error) {
|
||||
return sb.sectors.storage.ReaderSeq(ctx, id.Ref(), storiface.FTPiece)
|
||||
}
|
||||
|
||||
func (sb *SealCalls) RemovePiece(ctx context.Context, id storiface.PieceNumber) error {
|
||||
return sb.sectors.storage.Remove(ctx, id.Ref().ID, storiface.FTPiece, true, nil)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package lpffi
|
||||
package ffi
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -19,8 +19,8 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
proof2 "github.com/filecoin-project/go-state-types/proof"
|
||||
|
||||
"github.com/filecoin-project/lotus/curiosrc/proof"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/provider/lpproof"
|
||||
"github.com/filecoin-project/lotus/storage/paths"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/proofpaths"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
@ -42,7 +42,7 @@ type SealCalls struct {
|
||||
externCalls ExternalSealer*/
|
||||
}
|
||||
|
||||
func NewSealCalls(st paths.Store, ls *paths.Local, si paths.SectorIndex) *SealCalls {
|
||||
func NewSealCalls(st *paths.Remote, ls *paths.Local, si paths.SectorIndex) *SealCalls {
|
||||
return &SealCalls{
|
||||
sectors: &storageProvider{
|
||||
storage: st,
|
||||
@ -54,7 +54,7 @@ func NewSealCalls(st paths.Store, ls *paths.Local, si paths.SectorIndex) *SealCa
|
||||
}
|
||||
|
||||
type storageProvider struct {
|
||||
storage paths.Store
|
||||
storage *paths.Remote
|
||||
localStore *paths.Local
|
||||
sindex paths.SectorIndex
|
||||
storageReservations *xsync.MapOf[harmonytask.TaskID, *StorageReservation]
|
||||
@ -69,7 +69,7 @@ func (l *storageProvider) AcquireSector(ctx context.Context, taskID *harmonytask
|
||||
if taskID != nil {
|
||||
resv, ok = l.storageReservations.Load(*taskID)
|
||||
}
|
||||
if ok {
|
||||
if ok && resv != nil {
|
||||
if resv.Alloc != allocate || resv.Existing != existing {
|
||||
// this should never happen, only when task definition is wrong
|
||||
return storiface.SectorPaths{}, nil, xerrors.Errorf("storage reservation type mismatch")
|
||||
@ -78,6 +78,7 @@ func (l *storageProvider) AcquireSector(ctx context.Context, taskID *harmonytask
|
||||
log.Debugw("using existing storage reservation", "task", taskID, "sector", sector, "existing", existing, "allocate", allocate)
|
||||
|
||||
paths = resv.Paths
|
||||
storageIDs = resv.PathIDs
|
||||
releaseStorage = resv.Release
|
||||
} else {
|
||||
var err error
|
||||
@ -151,7 +152,7 @@ func (sb *SealCalls) TreeD(ctx context.Context, sector storiface.SectorRef, size
|
||||
}
|
||||
defer releaseSector()
|
||||
|
||||
return lpproof.BuildTreeD(data, unpaddedData, filepath.Join(paths.Cache, proofpaths.TreeDName), size)
|
||||
return proof.BuildTreeD(data, unpaddedData, filepath.Join(paths.Cache, proofpaths.TreeDName), size)
|
||||
}
|
||||
|
||||
func (sb *SealCalls) TreeRC(ctx context.Context, sector storiface.SectorRef, unsealed cid.Cid) (cid.Cid, cid.Cid, error) {
|
@ -1,4 +1,4 @@
|
||||
package lpffi
|
||||
package ffi
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,4 +1,4 @@
|
||||
package lpmarket
|
||||
package market
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -17,8 +17,8 @@ import (
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/curiosrc/seal"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/provider/lpseal"
|
||||
)
|
||||
|
||||
type Ingester interface {
|
||||
@ -72,7 +72,7 @@ func (p *PieceIngester) AllocatePieceToSector(ctx context.Context, maddr address
|
||||
return api.SectorOffset{}, xerrors.Errorf("getting miner ID: %w", err)
|
||||
}
|
||||
|
||||
num, err := lpseal.AllocateSectorNumbers(ctx, p.api, p.db, maddr, 1, func(tx *harmonydb.Tx, numbers []abi.SectorNumber) (bool, error) {
|
||||
num, err := seal.AllocateSectorNumbers(ctx, p.api, p.db, maddr, 1, func(tx *harmonydb.Tx, numbers []abi.SectorNumber) (bool, error) {
|
||||
if len(numbers) != 1 {
|
||||
return false, xerrors.Errorf("expected one sector number")
|
||||
}
|
@ -20,9 +20,9 @@ import (
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/curiosrc/market"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
"github.com/filecoin-project/lotus/provider/lpmarket"
|
||||
"github.com/filecoin-project/lotus/storage/paths"
|
||||
sealing "github.com/filecoin-project/lotus/storage/pipeline"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
@ -37,12 +37,12 @@ type LMRPCProvider struct {
|
||||
|
||||
ssize abi.SectorSize
|
||||
|
||||
pi lpmarket.Ingester
|
||||
pi market.Ingester
|
||||
db *harmonydb.DB
|
||||
confLayer string
|
||||
}
|
||||
|
||||
func NewLMRPCProvider(si paths.SectorIndex, full api.FullNode, maddr address.Address, minerID abi.ActorID, ssize abi.SectorSize, pi lpmarket.Ingester, db *harmonydb.DB, confLayer string) *LMRPCProvider {
|
||||
func NewLMRPCProvider(si paths.SectorIndex, full api.FullNode, maddr address.Address, minerID abi.ActorID, ssize abi.SectorSize, pi market.Ingester, db *harmonydb.DB, confLayer string) *LMRPCProvider {
|
||||
return &LMRPCProvider{
|
||||
si: si,
|
||||
full: full,
|
||||
@ -343,7 +343,7 @@ func (l *LMRPCProvider) AuthNew(ctx context.Context, perms []auth.Permission) ([
|
||||
return nil, xerrors.Errorf("no harmony config found")
|
||||
}
|
||||
|
||||
lp := config.DefaultLotusProvider()
|
||||
lp := config.DefaultCurioConfig()
|
||||
if _, err := toml.Decode(cs[0].Config, lp); err != nil {
|
||||
return nil, xerrors.Errorf("decode harmony config: %w", err)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package lpmessage
|
||||
package message
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -22,7 +22,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/lib/promise"
|
||||
)
|
||||
|
||||
var log = logging.Logger("lpmessage")
|
||||
var log = logging.Logger("curio/message")
|
||||
|
||||
var SendLockedWait = 100 * time.Millisecond
|
||||
|
||||
@ -187,7 +187,7 @@ func (s *SendTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done b
|
||||
} else {
|
||||
// Note: this handles an unlikely edge-case:
|
||||
// We have previously signed the message but either failed to send it or failed to update the db
|
||||
// note that when that happens the likely cause is the provider process losing its db connection
|
||||
// note that when that happens the likely cause is the curio process losing its db connection
|
||||
// or getting killed before it can update the db. In that case the message lock will still be held
|
||||
// so it will be safe to rebroadcast the signed message
|
||||
|
@ -1,4 +1,4 @@
|
||||
package lpmessage
|
||||
package message
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -12,9 +12,9 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/curiosrc/chainsched"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/provider/chainsched"
|
||||
)
|
||||
|
||||
const MinConfidence = 6
|
||||
@ -38,7 +38,7 @@ type MessageWatcher struct {
|
||||
bestTs atomic.Pointer[types.TipSetKey]
|
||||
}
|
||||
|
||||
func NewMessageWatcher(db *harmonydb.DB, ht *harmonytask.TaskEngine, pcs *chainsched.ProviderChainSched, api MessageWaiterApi) (*MessageWatcher, error) {
|
||||
func NewMessageWatcher(db *harmonydb.DB, ht *harmonytask.TaskEngine, pcs *chainsched.CurioChainSched, api MessageWaiterApi) (*MessageWatcher, error) {
|
||||
mw := &MessageWatcher{
|
||||
db: db,
|
||||
ht: ht,
|
@ -14,7 +14,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/storage/ctladdr"
|
||||
)
|
||||
|
||||
var log = logging.Logger("multictladdr")
|
||||
var log = logging.Logger("curio/multictladdr")
|
||||
|
||||
type MultiAddressSelector struct {
|
||||
MinerMap map[address.Address]api.AddressConfig
|
130
curiosrc/piece/task_cleanup_piece.go
Normal file
130
curiosrc/piece/task_cleanup_piece.go
Normal file
@ -0,0 +1,130 @@
|
||||
package piece
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/curiosrc/ffi"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/resources"
|
||||
"github.com/filecoin-project/lotus/lib/promise"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
|
||||
type CleanupPieceTask struct {
|
||||
max int
|
||||
db *harmonydb.DB
|
||||
sc *ffi.SealCalls
|
||||
|
||||
TF promise.Promise[harmonytask.AddTaskFunc]
|
||||
}
|
||||
|
||||
func NewCleanupPieceTask(db *harmonydb.DB, sc *ffi.SealCalls, max int) *CleanupPieceTask {
|
||||
pt := &CleanupPieceTask{
|
||||
db: db,
|
||||
sc: sc,
|
||||
|
||||
max: max,
|
||||
}
|
||||
go pt.pollCleanupTasks(context.Background())
|
||||
return pt
|
||||
}
|
||||
|
||||
func (c *CleanupPieceTask) pollCleanupTasks(ctx context.Context) {
|
||||
for {
|
||||
// select pieces with no refs and null cleanup_task_id
|
||||
var pieceIDs []struct {
|
||||
ID storiface.PieceNumber `db:"id"`
|
||||
}
|
||||
|
||||
err := c.db.Select(ctx, &pieceIDs, `SELECT id FROM parked_pieces WHERE cleanup_task_id IS NULL AND (SELECT count(*) FROM parked_piece_refs WHERE piece_id = parked_pieces.id) = 0`)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get parked pieces: %s", err)
|
||||
time.Sleep(PieceParkPollInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
if len(pieceIDs) == 0 {
|
||||
time.Sleep(PieceParkPollInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, pieceID := range pieceIDs {
|
||||
pieceID := pieceID
|
||||
|
||||
// create a task for each piece
|
||||
c.TF.Val(ctx)(func(id harmonytask.TaskID, tx *harmonydb.Tx) (shouldCommit bool, err error) {
|
||||
// update
|
||||
n, err := tx.Exec(`UPDATE parked_pieces SET cleanup_task_id = $1 WHERE id = $2 AND (SELECT count(*) FROM parked_piece_refs WHERE piece_id = parked_pieces.id) = 0`, id, pieceID.ID)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("updating parked piece: %w", err)
|
||||
}
|
||||
|
||||
// commit only if we updated the piece
|
||||
return n > 0, nil
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CleanupPieceTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done bool, err error) {
|
||||
ctx := context.Background()
|
||||
|
||||
// select by cleanup_task_id
|
||||
var pieceID int64
|
||||
|
||||
err = c.db.QueryRow(ctx, "SELECT id FROM parked_pieces WHERE cleanup_task_id = $1", taskID).Scan(&pieceID)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("query parked_piece: %w", err)
|
||||
}
|
||||
|
||||
// delete from parked_pieces where id = $1 where ref count = 0
|
||||
// note: we delete from the db first because that guarantees that the piece is no longer in use
|
||||
// if storage delete fails, it will be retried later is other cleanup tasks
|
||||
n, err := c.db.Exec(ctx, "DELETE FROM parked_pieces WHERE id = $1 AND (SELECT count(*) FROM parked_piece_refs WHERE piece_id = $1) = 0", pieceID)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("delete parked_piece: %w", err)
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// remove from storage
|
||||
err = c.sc.RemovePiece(ctx, storiface.PieceNumber(pieceID))
|
||||
if err != nil {
|
||||
log.Errorw("remove piece", "piece_id", pieceID, "error", err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (c *CleanupPieceTask) CanAccept(ids []harmonytask.TaskID, engine *harmonytask.TaskEngine) (*harmonytask.TaskID, error) {
|
||||
// the remove call runs on paths.Remote storage, so it doesn't really matter where it runs
|
||||
|
||||
id := ids[0]
|
||||
return &id, nil
|
||||
}
|
||||
|
||||
func (c *CleanupPieceTask) TypeDetails() harmonytask.TaskTypeDetails {
|
||||
return harmonytask.TaskTypeDetails{
|
||||
Max: c.max,
|
||||
Name: "DropPiece",
|
||||
Cost: resources.Resources{
|
||||
Cpu: 1,
|
||||
Gpu: 0,
|
||||
Ram: 64 << 20,
|
||||
Storage: nil,
|
||||
},
|
||||
MaxFailures: 10,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CleanupPieceTask) Adder(taskFunc harmonytask.AddTaskFunc) {
|
||||
c.TF.Set(taskFunc)
|
||||
}
|
||||
|
||||
var _ harmonytask.TaskInterface = &CleanupPieceTask{}
|
220
curiosrc/piece/task_park_piece.go
Normal file
220
curiosrc/piece/task_park_piece.go
Normal file
@ -0,0 +1,220 @@
|
||||
package piece
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/curiosrc/ffi"
|
||||
"github.com/filecoin-project/lotus/curiosrc/seal"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/resources"
|
||||
"github.com/filecoin-project/lotus/lib/promise"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
|
||||
var log = logging.Logger("lppiece")
|
||||
var PieceParkPollInterval = time.Second * 15
|
||||
|
||||
// ParkPieceTask gets a piece from some origin, and parks it in storage
|
||||
// Pieces are always f00, piece ID is mapped to pieceCID in the DB
|
||||
type ParkPieceTask struct {
|
||||
db *harmonydb.DB
|
||||
sc *ffi.SealCalls
|
||||
|
||||
TF promise.Promise[harmonytask.AddTaskFunc]
|
||||
|
||||
max int
|
||||
}
|
||||
|
||||
func NewParkPieceTask(db *harmonydb.DB, sc *ffi.SealCalls, max int) *ParkPieceTask {
|
||||
pt := &ParkPieceTask{
|
||||
db: db,
|
||||
sc: sc,
|
||||
|
||||
max: max,
|
||||
}
|
||||
go pt.pollPieceTasks(context.Background())
|
||||
return pt
|
||||
}
|
||||
|
||||
func (p *ParkPieceTask) pollPieceTasks(ctx context.Context) {
|
||||
for {
|
||||
// select parked pieces with no task_id
|
||||
var pieceIDs []struct {
|
||||
ID storiface.PieceNumber `db:"id"`
|
||||
}
|
||||
|
||||
err := p.db.Select(ctx, &pieceIDs, `SELECT id FROM parked_pieces WHERE complete = FALSE AND task_id IS NULL`)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get parked pieces: %s", err)
|
||||
time.Sleep(PieceParkPollInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
if len(pieceIDs) == 0 {
|
||||
time.Sleep(PieceParkPollInterval)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, pieceID := range pieceIDs {
|
||||
pieceID := pieceID
|
||||
|
||||
// create a task for each piece
|
||||
p.TF.Val(ctx)(func(id harmonytask.TaskID, tx *harmonydb.Tx) (shouldCommit bool, err error) {
|
||||
// update
|
||||
n, err := tx.Exec(`UPDATE parked_pieces SET task_id = $1 WHERE id = $2 AND complete = FALSE AND task_id IS NULL`, id, pieceID.ID)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("updating parked piece: %w", err)
|
||||
}
|
||||
|
||||
// commit only if we updated the piece
|
||||
return n > 0, nil
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ParkPieceTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done bool, err error) {
|
||||
ctx := context.Background()
|
||||
|
||||
// Define a struct to hold piece data.
|
||||
var piecesData []struct {
|
||||
PieceID int64 `db:"id"`
|
||||
PieceCreatedAt time.Time `db:"created_at"`
|
||||
PieceCID string `db:"piece_cid"`
|
||||
Complete bool `db:"complete"`
|
||||
PiecePaddedSize int64 `db:"piece_padded_size"`
|
||||
PieceRawSize string `db:"piece_raw_size"`
|
||||
}
|
||||
|
||||
// Select the piece data using the task ID.
|
||||
err = p.db.Select(ctx, &piecesData, `
|
||||
SELECT id, created_at, piece_cid, complete, piece_padded_size, piece_raw_size
|
||||
FROM parked_pieces
|
||||
WHERE task_id = $1
|
||||
`, taskID)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("fetching piece data: %w", err)
|
||||
}
|
||||
|
||||
if len(piecesData) == 0 {
|
||||
return false, xerrors.Errorf("no piece data found for task_id: %d", taskID)
|
||||
}
|
||||
|
||||
pieceData := piecesData[0]
|
||||
|
||||
if pieceData.Complete {
|
||||
log.Warnw("park piece task already complete", "task_id", taskID, "piece_cid", pieceData.PieceCID)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Define a struct for reference data.
|
||||
var refData []struct {
|
||||
DataURL string `db:"data_url"`
|
||||
DataHeaders json.RawMessage `db:"data_headers"`
|
||||
}
|
||||
|
||||
// Now, select the first reference data that has a URL.
|
||||
err = p.db.Select(ctx, &refData, `
|
||||
SELECT data_url, data_headers
|
||||
FROM parked_piece_refs
|
||||
WHERE piece_id = $1 AND data_url IS NOT NULL
|
||||
LIMIT 1
|
||||
`, pieceData.PieceID)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("fetching reference data: %w", err)
|
||||
}
|
||||
|
||||
if len(refData) == 0 {
|
||||
return false, xerrors.Errorf("no refs found for piece_id: %d", pieceData.PieceID)
|
||||
}
|
||||
|
||||
// Convert piece_raw_size from string to int64.
|
||||
pieceRawSize, err := strconv.ParseInt(pieceData.PieceRawSize, 10, 64)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("parsing piece raw size: %w", err)
|
||||
}
|
||||
|
||||
if refData[0].DataURL != "" {
|
||||
upr := &seal.UrlPieceReader{
|
||||
Url: refData[0].DataURL,
|
||||
RawSize: pieceRawSize,
|
||||
}
|
||||
defer func() {
|
||||
_ = upr.Close()
|
||||
}()
|
||||
|
||||
pnum := storiface.PieceNumber(pieceData.PieceID)
|
||||
|
||||
if err := p.sc.WritePiece(ctx, pnum, pieceRawSize, upr); err != nil {
|
||||
return false, xerrors.Errorf("write piece: %w", err)
|
||||
}
|
||||
|
||||
// Update the piece as complete after a successful write.
|
||||
_, err = p.db.Exec(ctx, `UPDATE parked_pieces SET complete = TRUE WHERE id = $1`, pieceData.PieceID)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("marking piece as complete: %w", err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// If no URL is found, this indicates an issue since at least one URL is expected.
|
||||
return false, xerrors.Errorf("no data URL found for piece_id: %d", pieceData.PieceID)
|
||||
}
|
||||
|
||||
func (p *ParkPieceTask) CanAccept(ids []harmonytask.TaskID, engine *harmonytask.TaskEngine) (*harmonytask.TaskID, error) {
|
||||
id := ids[0]
|
||||
return &id, nil
|
||||
}
|
||||
|
||||
func (p *ParkPieceTask) TypeDetails() harmonytask.TaskTypeDetails {
|
||||
const maxSizePiece = 64 << 30
|
||||
|
||||
return harmonytask.TaskTypeDetails{
|
||||
Max: p.max,
|
||||
Name: "ParkPiece",
|
||||
Cost: resources.Resources{
|
||||
Cpu: 1,
|
||||
Gpu: 0,
|
||||
Ram: 64 << 20,
|
||||
Storage: p.sc.Storage(p.taskToRef, storiface.FTPiece, storiface.FTNone, maxSizePiece, storiface.PathSealing),
|
||||
},
|
||||
MaxFailures: 10,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ParkPieceTask) taskToRef(id harmonytask.TaskID) (ffi.SectorRef, error) {
|
||||
var pieceIDs []struct {
|
||||
ID storiface.PieceNumber `db:"id"`
|
||||
}
|
||||
|
||||
err := p.db.Select(context.Background(), &pieceIDs, `SELECT id FROM parked_pieces WHERE task_id = $1`, id)
|
||||
if err != nil {
|
||||
return ffi.SectorRef{}, xerrors.Errorf("getting piece id: %w", err)
|
||||
}
|
||||
|
||||
if len(pieceIDs) != 1 {
|
||||
return ffi.SectorRef{}, xerrors.Errorf("expected 1 piece id, got %d", len(pieceIDs))
|
||||
}
|
||||
|
||||
pref := pieceIDs[0].ID.Ref()
|
||||
|
||||
return ffi.SectorRef{
|
||||
SpID: int64(pref.ID.Miner),
|
||||
SectorNumber: int64(pref.ID.Number),
|
||||
RegSealProof: pref.ProofType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *ParkPieceTask) Adder(taskFunc harmonytask.AddTaskFunc) {
|
||||
p.TF.Set(taskFunc)
|
||||
}
|
||||
|
||||
var _ harmonytask.TaskInterface = &ParkPieceTask{}
|
@ -1,4 +1,4 @@
|
||||
package lpproof
|
||||
package proof
|
||||
|
||||
import (
|
||||
"io"
|
@ -1,4 +1,4 @@
|
||||
package lpproof
|
||||
package proof
|
||||
|
||||
import (
|
||||
"bufio"
|
51
curiosrc/seal/finalize_pieces.go
Normal file
51
curiosrc/seal/finalize_pieces.go
Normal file
@ -0,0 +1,51 @@
|
||||
package seal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
)
|
||||
|
||||
func DropSectorPieceRefs(ctx context.Context, db *harmonydb.DB, sid abi.SectorID) error {
|
||||
//_, err := db.Exec(ctx, `SELECT FROM sectors_sdr_initial_pieces WHERE sp_id = $1 AND sector_number = $2`, sid.Miner, sid.Number)
|
||||
|
||||
var PieceURL []struct {
|
||||
URL string `db:"data_url"`
|
||||
}
|
||||
|
||||
err := db.Select(ctx, &PieceURL, `SELECT data_url FROM sectors_sdr_initial_pieces WHERE sp_id = $1 AND sector_number = $2`, sid.Miner, sid.Number)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting piece url: %w", err)
|
||||
}
|
||||
|
||||
for _, pu := range PieceURL {
|
||||
gourl, err := url.Parse(pu.URL)
|
||||
if err != nil {
|
||||
log.Errorw("failed to parse piece url", "url", pu.URL, "error", err, "miner", sid.Miner, "sector", sid.Number)
|
||||
continue
|
||||
}
|
||||
|
||||
if gourl.Scheme == "pieceref" {
|
||||
refID, err := strconv.ParseInt(gourl.Opaque, 10, 64)
|
||||
if err != nil {
|
||||
log.Errorw("failed to parse piece ref id", "url", pu.URL, "error", err, "miner", sid.Miner, "sector", sid.Number)
|
||||
continue
|
||||
}
|
||||
|
||||
n, err := db.Exec(ctx, `DELETE FROM parked_piece_refs WHERE ref_id = $1`, refID)
|
||||
if err != nil {
|
||||
log.Errorw("failed to delete piece ref", "url", pu.URL, "error", err, "miner", sid.Miner, "sector", sid.Number)
|
||||
}
|
||||
|
||||
log.Debugw("deleted piece ref", "url", pu.URL, "miner", sid.Miner, "sector", sid.Number, "rows", n)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,4 +1,4 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,4 +1,4 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,4 +1,4 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,4 +1,4 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -7,21 +7,21 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/curiosrc/ffi"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/resources"
|
||||
"github.com/filecoin-project/lotus/provider/lpffi"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
|
||||
type FinalizeTask struct {
|
||||
max int
|
||||
sp *SealPoller
|
||||
sc *lpffi.SealCalls
|
||||
sc *ffi.SealCalls
|
||||
db *harmonydb.DB
|
||||
}
|
||||
|
||||
func NewFinalizeTask(max int, sp *SealPoller, sc *lpffi.SealCalls, db *harmonydb.DB) *FinalizeTask {
|
||||
func NewFinalizeTask(max int, sp *SealPoller, sc *ffi.SealCalls, db *harmonydb.DB) *FinalizeTask {
|
||||
return &FinalizeTask{
|
||||
max: max,
|
||||
sp: sp,
|
||||
@ -69,6 +69,10 @@ func (f *FinalizeTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (do
|
||||
return false, xerrors.Errorf("finalizing sector: %w", err)
|
||||
}
|
||||
|
||||
if err := DropSectorPieceRefs(ctx, f.db, sector.ID); err != nil {
|
||||
return false, xerrors.Errorf("dropping sector piece refs: %w", err)
|
||||
}
|
||||
|
||||
// set after_finalize
|
||||
_, err = f.db.Exec(ctx, `update sectors_sdr_pipeline set after_finalize=true where task_id_finalize=$1`, taskID)
|
||||
if err != nil {
|
||||
@ -86,7 +90,7 @@ func (f *FinalizeTask) CanAccept(ids []harmonytask.TaskID, engine *harmonytask.T
|
||||
StorageID string `db:"storage_id"`
|
||||
}
|
||||
|
||||
if 4 != storiface.FTCache {
|
||||
if storiface.FTCache != 4 {
|
||||
panic("storiface.FTCache != 4")
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -7,22 +7,22 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/curiosrc/ffi"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/resources"
|
||||
"github.com/filecoin-project/lotus/provider/lpffi"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
|
||||
type MoveStorageTask struct {
|
||||
sp *SealPoller
|
||||
sc *lpffi.SealCalls
|
||||
sc *ffi.SealCalls
|
||||
db *harmonydb.DB
|
||||
|
||||
max int
|
||||
}
|
||||
|
||||
func NewMoveStorageTask(sp *SealPoller, sc *lpffi.SealCalls, db *harmonydb.DB, max int) *MoveStorageTask {
|
||||
func NewMoveStorageTask(sp *SealPoller, sc *ffi.SealCalls, db *harmonydb.DB, max int) *MoveStorageTask {
|
||||
return &MoveStorageTask{
|
||||
max: max,
|
||||
sp: sp,
|
@ -1,4 +1,4 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -12,10 +12,10 @@ import (
|
||||
"github.com/filecoin-project/go-state-types/crypto"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/curiosrc/ffi"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/resources"
|
||||
"github.com/filecoin-project/lotus/provider/lpffi"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
|
||||
@ -28,12 +28,12 @@ type PoRepTask struct {
|
||||
db *harmonydb.DB
|
||||
api PoRepAPI
|
||||
sp *SealPoller
|
||||
sc *lpffi.SealCalls
|
||||
sc *ffi.SealCalls
|
||||
|
||||
max int
|
||||
}
|
||||
|
||||
func NewPoRepTask(db *harmonydb.DB, api PoRepAPI, sp *SealPoller, sc *lpffi.SealCalls, maxPoRep int) *PoRepTask {
|
||||
func NewPoRepTask(db *harmonydb.DB, api PoRepAPI, sp *SealPoller, sc *ffi.SealCalls, maxPoRep int) *PoRepTask {
|
||||
return &PoRepTask{
|
||||
db: db,
|
||||
api: api,
|
@ -1,4 +1,4 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -16,10 +16,10 @@ import (
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/curiosrc/ffi"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/resources"
|
||||
"github.com/filecoin-project/lotus/provider/lpffi"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
|
||||
@ -35,12 +35,12 @@ type SDRTask struct {
|
||||
db *harmonydb.DB
|
||||
sp *SealPoller
|
||||
|
||||
sc *lpffi.SealCalls
|
||||
sc *ffi.SealCalls
|
||||
|
||||
max int
|
||||
}
|
||||
|
||||
func NewSDRTask(api SDRAPI, db *harmonydb.DB, sp *SealPoller, sc *lpffi.SealCalls, maxSDR int) *SDRTask {
|
||||
func NewSDRTask(api SDRAPI, db *harmonydb.DB, sp *SealPoller, sc *ffi.SealCalls, maxSDR int) *SDRTask {
|
||||
return &SDRTask{
|
||||
api: api,
|
||||
db: db,
|
||||
@ -187,8 +187,6 @@ func (s *SDRTask) getTicket(ctx context.Context, maddr address.Address) (abi.Sea
|
||||
}
|
||||
|
||||
func (s *SDRTask) CanAccept(ids []harmonytask.TaskID, engine *harmonytask.TaskEngine) (*harmonytask.TaskID, error) {
|
||||
// todo check storage (reserve too?)
|
||||
|
||||
id := ids[0]
|
||||
return &id, nil
|
||||
}
|
||||
@ -223,16 +221,16 @@ func (s *SDRTask) Adder(taskFunc harmonytask.AddTaskFunc) {
|
||||
s.sp.pollers[pollerSDR].Set(taskFunc)
|
||||
}
|
||||
|
||||
func (s *SDRTask) taskToSector(id harmonytask.TaskID) (lpffi.SectorRef, error) {
|
||||
var refs []lpffi.SectorRef
|
||||
func (s *SDRTask) taskToSector(id harmonytask.TaskID) (ffi.SectorRef, error) {
|
||||
var refs []ffi.SectorRef
|
||||
|
||||
err := s.db.Select(context.Background(), &refs, `SELECT sp_id, sector_number, reg_seal_proof FROM sectors_sdr_pipeline WHERE task_id_sdr = $1`, id)
|
||||
if err != nil {
|
||||
return lpffi.SectorRef{}, xerrors.Errorf("getting sector ref: %w", err)
|
||||
return ffi.SectorRef{}, xerrors.Errorf("getting sector ref: %w", err)
|
||||
}
|
||||
|
||||
if len(refs) != 1 {
|
||||
return lpffi.SectorRef{}, xerrors.Errorf("expected 1 sector ref, got %d", len(refs))
|
||||
return ffi.SectorRef{}, xerrors.Errorf("expected 1 sector ref, got %d", len(refs))
|
||||
}
|
||||
|
||||
return refs[0], nil
|
@ -1,4 +1,4 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -14,11 +14,11 @@ import (
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/curiosrc/message"
|
||||
"github.com/filecoin-project/lotus/curiosrc/multictladdr"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/resources"
|
||||
"github.com/filecoin-project/lotus/provider/lpmessage"
|
||||
"github.com/filecoin-project/lotus/provider/multictladdr"
|
||||
"github.com/filecoin-project/lotus/storage/ctladdr"
|
||||
)
|
||||
|
||||
@ -35,13 +35,13 @@ type SubmitCommitTask struct {
|
||||
db *harmonydb.DB
|
||||
api SubmitCommitAPI
|
||||
|
||||
sender *lpmessage.Sender
|
||||
sender *message.Sender
|
||||
as *multictladdr.MultiAddressSelector
|
||||
|
||||
maxFee types.FIL
|
||||
}
|
||||
|
||||
func NewSubmitCommitTask(sp *SealPoller, db *harmonydb.DB, api SubmitCommitAPI, sender *lpmessage.Sender, as *multictladdr.MultiAddressSelector, maxFee types.FIL) *SubmitCommitTask {
|
||||
func NewSubmitCommitTask(sp *SealPoller, db *harmonydb.DB, api SubmitCommitAPI, sender *message.Sender, as *multictladdr.MultiAddressSelector, maxFee types.FIL) *SubmitCommitTask {
|
||||
return &SubmitCommitTask{
|
||||
sp: sp,
|
||||
db: db,
|
@ -1,4 +1,4 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -9,24 +9,28 @@ import (
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/builtin"
|
||||
miner12 "github.com/filecoin-project/go-state-types/builtin/v12/miner"
|
||||
"github.com/filecoin-project/go-state-types/network"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||
"github.com/filecoin-project/lotus/chain/actors/policy"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/curiosrc/message"
|
||||
"github.com/filecoin-project/lotus/curiosrc/multictladdr"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/resources"
|
||||
"github.com/filecoin-project/lotus/provider/lpmessage"
|
||||
"github.com/filecoin-project/lotus/provider/multictladdr"
|
||||
"github.com/filecoin-project/lotus/storage/ctladdr"
|
||||
)
|
||||
|
||||
type SubmitPrecommitTaskApi interface {
|
||||
StateMinerPreCommitDepositForPower(context.Context, address.Address, miner.SectorPreCommitInfo, types.TipSetKey) (big.Int, error)
|
||||
StateMinerInfo(context.Context, address.Address, types.TipSetKey) (api.MinerInfo, error)
|
||||
StateNetworkVersion(context.Context, types.TipSetKey) (network.Version, error)
|
||||
ctladdr.NodeApi
|
||||
}
|
||||
|
||||
@ -34,13 +38,13 @@ type SubmitPrecommitTask struct {
|
||||
sp *SealPoller
|
||||
db *harmonydb.DB
|
||||
api SubmitPrecommitTaskApi
|
||||
sender *lpmessage.Sender
|
||||
sender *message.Sender
|
||||
as *multictladdr.MultiAddressSelector
|
||||
|
||||
maxFee types.FIL
|
||||
}
|
||||
|
||||
func NewSubmitPrecommitTask(sp *SealPoller, db *harmonydb.DB, api SubmitPrecommitTaskApi, sender *lpmessage.Sender, as *multictladdr.MultiAddressSelector, maxFee types.FIL) *SubmitPrecommitTask {
|
||||
func NewSubmitPrecommitTask(sp *SealPoller, db *harmonydb.DB, api SubmitPrecommitTaskApi, sender *message.Sender, as *multictladdr.MultiAddressSelector, maxFee types.FIL) *SubmitPrecommitTask {
|
||||
return &SubmitPrecommitTask{
|
||||
sp: sp,
|
||||
db: db,
|
||||
@ -136,6 +140,23 @@ func (s *SubmitPrecommitTask) Do(taskID harmonytask.TaskID, stillOwned func() bo
|
||||
}
|
||||
}
|
||||
|
||||
nv, err := s.api.StateNetworkVersion(ctx, types.EmptyTSK)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("getting network version: %w", err)
|
||||
}
|
||||
av, err := actorstypes.VersionForNetwork(nv)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("failed to get actors version: %w", err)
|
||||
}
|
||||
msd, err := policy.GetMaxProveCommitDuration(av, sectorParams.RegSealProof)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("failed to get max prove commit duration: %w", err)
|
||||
}
|
||||
|
||||
if minExpiration := sectorParams.TicketEpoch + policy.MaxPreCommitRandomnessLookback + msd + miner.MinSectorExpiration; params.Sectors[0].Expiration < minExpiration {
|
||||
params.Sectors[0].Expiration = minExpiration
|
||||
}
|
||||
|
||||
var pbuf bytes.Buffer
|
||||
if err := params.MarshalCBOR(&pbuf); err != nil {
|
||||
return false, xerrors.Errorf("serializing params: %w", err)
|
@ -1,9 +1,11 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
"golang.org/x/xerrors"
|
||||
@ -13,10 +15,10 @@ import (
|
||||
"github.com/filecoin-project/go-padreader"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
|
||||
"github.com/filecoin-project/lotus/curiosrc/ffi"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/resources"
|
||||
"github.com/filecoin-project/lotus/provider/lpffi"
|
||||
"github.com/filecoin-project/lotus/storage/pipeline/lib/nullreader"
|
||||
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
||||
)
|
||||
@ -24,12 +26,12 @@ import (
|
||||
type TreesTask struct {
|
||||
sp *SealPoller
|
||||
db *harmonydb.DB
|
||||
sc *lpffi.SealCalls
|
||||
sc *ffi.SealCalls
|
||||
|
||||
max int
|
||||
}
|
||||
|
||||
func NewTreesTask(sp *SealPoller, db *harmonydb.DB, sc *lpffi.SealCalls, maxTrees int) *TreesTask {
|
||||
func NewTreesTask(sp *SealPoller, db *harmonydb.DB, sc *ffi.SealCalls, maxTrees int) *TreesTask {
|
||||
return &TreesTask{
|
||||
sp: sp,
|
||||
db: db,
|
||||
@ -88,6 +90,15 @@ func (t *TreesTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done
|
||||
var dataReader io.Reader
|
||||
var unpaddedData bool
|
||||
|
||||
var closers []io.Closer
|
||||
defer func() {
|
||||
for _, c := range closers {
|
||||
if err := c.Close(); err != nil {
|
||||
log.Errorw("error closing piece reader", "error", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if len(pieces) > 0 {
|
||||
pieceInfos := make([]abi.PieceInfo, len(pieces))
|
||||
pieceReaders := make([]io.Reader, len(pieces))
|
||||
@ -106,10 +117,49 @@ func (t *TreesTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done
|
||||
|
||||
// make pieceReader
|
||||
if p.DataUrl != nil {
|
||||
dataUrl := *p.DataUrl
|
||||
|
||||
goUrl, err := url.Parse(dataUrl)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("parsing data URL: %w", err)
|
||||
}
|
||||
|
||||
if goUrl.Scheme == "pieceref" {
|
||||
// url is to a piece reference
|
||||
|
||||
refNum, err := strconv.ParseInt(goUrl.Opaque, 10, 64)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("parsing piece reference number: %w", err)
|
||||
}
|
||||
|
||||
// get pieceID
|
||||
var pieceID []struct {
|
||||
PieceID storiface.PieceNumber `db:"piece_id"`
|
||||
}
|
||||
err = t.db.Select(ctx, &pieceID, `SELECT piece_id FROM parked_piece_refs WHERE ref_id = $1`, refNum)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("getting pieceID: %w", err)
|
||||
}
|
||||
|
||||
if len(pieceID) != 1 {
|
||||
return false, xerrors.Errorf("expected 1 pieceID, got %d", len(pieceID))
|
||||
}
|
||||
|
||||
pr, err := t.sc.PieceReader(ctx, pieceID[0].PieceID)
|
||||
if err != nil {
|
||||
return false, xerrors.Errorf("getting piece reader: %w", err)
|
||||
}
|
||||
|
||||
closers = append(closers, pr)
|
||||
|
||||
pieceReaders[i], _ = padreader.New(pr, uint64(*p.DataRawSize))
|
||||
} else {
|
||||
pieceReaders[i], _ = padreader.New(&UrlPieceReader{
|
||||
Url: *p.DataUrl,
|
||||
Url: dataUrl,
|
||||
RawSize: *p.DataRawSize,
|
||||
}, uint64(*p.DataRawSize))
|
||||
}
|
||||
|
||||
} else { // padding piece (w/o fr32 padding, added in TreeD)
|
||||
pieceReaders[i] = nullreader.NewNullReader(abi.PaddedPieceSize(p.PieceSize).Unpadded())
|
||||
}
|
||||
@ -200,6 +250,7 @@ type UrlPieceReader struct {
|
||||
RawSize int64 // the exact number of bytes read, if we read more or less that's an error
|
||||
|
||||
readSoFar int64
|
||||
closed bool
|
||||
active io.ReadCloser // auto-closed on EOF
|
||||
}
|
||||
|
||||
@ -239,6 +290,7 @@ func (u *UrlPieceReader) Read(p []byte) (n int, err error) {
|
||||
// If EOF is reached, close the reader
|
||||
if err == io.EOF {
|
||||
cerr := u.active.Close()
|
||||
u.closed = true
|
||||
if cerr != nil {
|
||||
log.Errorf("error closing http piece reader: %s", cerr)
|
||||
}
|
||||
@ -253,4 +305,13 @@ func (u *UrlPieceReader) Read(p []byte) (n int, err error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (u *UrlPieceReader) Close() error {
|
||||
if !u.closed {
|
||||
u.closed = true
|
||||
return u.active.Close()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ harmonytask.TaskInterface = &TreesTask{}
|
@ -1,4 +1,4 @@
|
||||
package lpseal
|
||||
package seal
|
||||
|
||||
import (
|
||||
"io"
|
@ -1,4 +1,4 @@
|
||||
// Package debug provides the API for various debug endpoints in lotus-provider.
|
||||
// Package debug provides the API for various debug endpoints in curio.
|
||||
package debug
|
||||
|
||||
import (
|
||||
@ -18,10 +18,10 @@ import (
|
||||
"github.com/filecoin-project/lotus/api/client"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
)
|
||||
|
||||
var log = logging.Logger("lp/web/debug")
|
||||
var log = logging.Logger("curio/web/debug")
|
||||
|
||||
type debug struct {
|
||||
*deps.Deps
|
13
curiosrc/web/api/routes.go
Normal file
13
curiosrc/web/api/routes.go
Normal file
@ -0,0 +1,13 @@
|
||||
// Package api provides the HTTP API for the lotus curio web gui.
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
"github.com/filecoin-project/lotus/curiosrc/web/api/debug"
|
||||
)
|
||||
|
||||
func Routes(r *mux.Router, deps *deps.Deps) {
|
||||
debug.Routes(r.PathPrefix("/debug").Subrouter(), deps)
|
||||
}
|
@ -8,7 +8,7 @@ import (
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/lotus/cmd/lotus-provider/deps"
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
)
|
||||
|
||||
//go:embed web/*
|
||||
@ -39,4 +39,4 @@ func Routes(r *mux.Router, deps *deps.Deps) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var log = logging.Logger("lpweb")
|
||||
var log = logging.Logger("curio/web")
|
@ -5,6 +5,7 @@ import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -32,6 +33,10 @@ type actorInfo struct {
|
||||
QualityAdjustedPower string
|
||||
RawBytePower string
|
||||
|
||||
ActorBalance, ActorAvailable, WorkerBalance string
|
||||
|
||||
Win1, Win7, Win30 int64
|
||||
|
||||
Deadlines []actorDeadline
|
||||
}
|
||||
|
||||
@ -98,7 +103,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("./provider/lpweb/hapi/web")
|
||||
fs := os.DirFS("./cmd/curio/web/hapi/web")
|
||||
a.t = template.Must(template.ParseFS(fs, "*"))
|
||||
}
|
||||
if err := a.t.ExecuteTemplate(w, name, data); err != nil {
|
||||
@ -107,10 +112,18 @@ func (a *app) executeTemplate(w http.ResponseWriter, name string, data interface
|
||||
}
|
||||
}
|
||||
|
||||
type machineRecentTask struct {
|
||||
TaskName string
|
||||
Success int64
|
||||
Fail int64
|
||||
}
|
||||
|
||||
type machineSummary struct {
|
||||
Address string
|
||||
ID int64
|
||||
SinceContact string
|
||||
|
||||
RecentTasks []*machineRecentTask
|
||||
}
|
||||
|
||||
type taskSummary struct {
|
||||
@ -133,7 +146,47 @@ type taskHistorySummary struct {
|
||||
}
|
||||
|
||||
func (a *app) clusterMachineSummary(ctx context.Context) ([]machineSummary, error) {
|
||||
rows, err := a.db.Query(ctx, "SELECT id, host_and_port, last_contact FROM harmony_machines")
|
||||
// First get task summary for tasks completed in the last 24 hours
|
||||
// NOTE: This query uses harmony_task_history_work_index, task history may get big
|
||||
tsrows, err := a.db.Query(ctx, `SELECT hist.completed_by_host_and_port, hist.name, hist.result, count(1) FROM harmony_task_history hist
|
||||
WHERE hist.work_end > now() - INTERVAL '1 day'
|
||||
GROUP BY hist.completed_by_host_and_port, hist.name, hist.result
|
||||
ORDER BY completed_by_host_and_port ASC`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tsrows.Close()
|
||||
|
||||
// Map of machine -> task -> recent task
|
||||
taskSummaries := map[string]map[string]*machineRecentTask{}
|
||||
|
||||
for tsrows.Next() {
|
||||
var taskName string
|
||||
var result bool
|
||||
var count int64
|
||||
var machine string
|
||||
|
||||
if err := tsrows.Scan(&machine, &taskName, &result, &count); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, ok := taskSummaries[machine]; !ok {
|
||||
taskSummaries[machine] = map[string]*machineRecentTask{}
|
||||
}
|
||||
|
||||
if _, ok := taskSummaries[machine][taskName]; !ok {
|
||||
taskSummaries[machine][taskName] = &machineRecentTask{TaskName: taskName}
|
||||
}
|
||||
|
||||
if result {
|
||||
taskSummaries[machine][taskName].Success = count
|
||||
} else {
|
||||
taskSummaries[machine][taskName].Fail = count
|
||||
}
|
||||
}
|
||||
|
||||
// Then machine summary
|
||||
rows, err := a.db.Query(ctx, "SELECT id, host_and_port, last_contact FROM harmony_machines order by host_and_port asc")
|
||||
if err != nil {
|
||||
return nil, err // Handle error
|
||||
}
|
||||
@ -150,6 +203,16 @@ func (a *app) clusterMachineSummary(ctx context.Context) ([]machineSummary, erro
|
||||
|
||||
m.SinceContact = time.Since(lastContact).Round(time.Second).String()
|
||||
|
||||
// Add recent tasks
|
||||
if ts, ok := taskSummaries[m.Address]; ok {
|
||||
for _, t := range ts {
|
||||
m.RecentTasks = append(m.RecentTasks, t)
|
||||
}
|
||||
sort.Slice(m.RecentTasks, func(i, j int) bool {
|
||||
return m.RecentTasks[i].TaskName < m.RecentTasks[j].TaskName
|
||||
})
|
||||
}
|
||||
|
||||
summaries = append(summaries, m)
|
||||
}
|
||||
return summaries, nil
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user