diff --git a/.github/workflows/cli_tests.yml b/.github/workflows/cli_tests.yml index 40138a1bbe..77f5b0cb1a 100644 --- a/.github/workflows/cli_tests.yml +++ b/.github/workflows/cli_tests.yml @@ -6,10 +6,8 @@ jobs: go: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - with: - fetch-depth: '0' - - uses: actions/setup-go@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: go-version: 1.20.5 diff --git a/.github/workflows/consensus_tests.yml b/.github/workflows/consensus_tests.yml deleted file mode 100644 index fd9eef1591..0000000000 --- a/.github/workflows/consensus_tests.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: Lava Consensus Tests - -on: [pull_request] - -jobs: - go: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: '0' - - uses: actions/setup-go@v3 - with: - go-version: 1.20.5 - - - # Setup Paths - - name: home - run: pwd && ls -l - - name: ls usr - run: ls -l /home/runner/work/lava/lava - - name: cp lava - run: cp -r ~/work/lava/lava ~/go/lava - - name: export PATH - run: export PATH=$PATH:/go:/go/bin:$(go env GOPATH)/bin:/usr/local:`pwd`:/home/runner/work/lava/lava/ - - name: export GOPATH - run: export GOPATH=$GOPATH:$(go env GOPATH):/go:/go/lava:/usr/local:`pwd` - - name: export LAVA - run: export LAVA=/home/runner/work/lava/lava - - name: go env - run: go env - - name: pwd - run: pwd - - name: tree - run: tree - - name: ls -l - run: ls -l - - ###################################################### - ### Run Consensus unitests - ###################################################### - - name: lava utils unit Tests - run: go test ./utils/... - - - name: lava common unit Tests - run: go test ./common/... - - - name: lava pairing unit Tests - run: go test ./x/pairing/... - - - name: lava epochstorage unit Tests - run: go test ./x/epochstorage/... - - - name: lava spec unit Tests - run: go test ./x/spec/... - - - name: lava conflict unit Tests - run: go test ./x/conflict/... - - - name: lava plans unit Tests - run: go test ./x/plans/... - - - name: lava projects unit Tests - run: go test ./x/projects/... - - - name: lava subscription unit Tests - run: go test ./x/subscription/... - - - name: lava dualstaking unit Tests - run: go test ./x/dualstaking/... - - - name: lava fixation unit Tests - run: go test ./x/fixationstore/... - - - name: lava timerstore unit Tests - run: go test ./x/timerstore/... - - - name: lava downtime unit Tests - run: go test ./x/downtime/... - - - name: lava rewards unit Tests - run: go test ./x/rewards/... diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml deleted file mode 100644 index 506375a45c..0000000000 --- a/.github/workflows/e2e.yml +++ /dev/null @@ -1,245 +0,0 @@ -name: Lava E2E Tests - -on: [pull_request] - -jobs: - test-protocol-e2e: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: "0" - - - uses: actions/setup-go@v3 - with: - go-version: 1.20.5 - - ###################################################### - ### Run Lava Protocol E2E Tests - ###################################################### - - name: Run Lava E2E Tests -timeout 1200s - run: go test ./testutil/e2e/ -run ^TestLavaProtocol$ -v -timeout 1200s # 20mins - - - name: tail -n 1000 Lavad Logs - if: always() - run: tail -n 1000 testutil/e2e/protocolLogs/00_StartLava.log - - - name: Print all warnings and errors from lavad - continue-on-error: true - if: always() - run: cat testutil/e2e/protocolLogs/00_StartLava.log | grep 'WRN |ERR ' - - - name: Stake Lava All Logs - if: always() - run: cat testutil/e2e/protocolLogs/01_stakeLava.log - - - name: Stake Lava Error Only Logs - if: always() - continue-on-error: true - run: cat testutil/e2e/protocolLogs/01_stakeLava_errors.log - - - name: head -n 300 JSON Proxy Logs - if: always() - run: head -n 300 testutil/e2e/protocolLogs/02_jsonProxy.log - - - name: tail -n 300 JSON Proxy Logs - if: always() - run: tail -n 300 testutil/e2e/protocolLogs/02_jsonProxy.log - - - name: JSON Proxy Error Only Logs - if: always() - continue-on-error: true - run: cat testutil/e2e/protocolLogs/02_jsonProxy_errors.log - - - name: JSON Provider All Logs - if: always() - run: grep "" testutil/e2e/protocolLogs/03_EthProvider* --exclude="*errors*" - - - name: JSON Provider Error Only Logs - if: always() - continue-on-error: true - run: grep "" testutil/e2e/protocolLogs/03_EthProvider* --include="*errors*" - - - name: JSON Consumer All Logs - if: always() - run: grep "" testutil/e2e/protocolLogs/04_jsonConsumer* --exclude="*errors*" - - - name: JSON Consumer Error Only Logs - if: always() - continue-on-error: true - run: grep "" testutil/e2e/protocolLogs/04_jsonConsumer* --include="*errors*" - - - name: Lava Provider All Logs - if: always() - run: grep "" testutil/e2e/protocolLogs/05_LavaProvider* --exclude="*errors*" - - - name: Lava Provider Error Only Logs - if: always() - continue-on-error: true - run: grep "" testutil/e2e/protocolLogs/05_LavaProvider* --include="*errors*" - - - name: Lava over Lava All Logs - if: always() - run: cat testutil/e2e/protocolLogs/07_lavaOverLava.log - - - name: Lava over Lava Error Only Logs - if: always() - continue-on-error: true - run: cat testutil/e2e/protocolLogs/07_lavaOverLava_errors.log - - - name: RPCConsumer Consumer All Logs - if: always() - run: grep "" testutil/e2e/protocolLogs/06_RPCConsumer* --exclude="*errors*" - - - name: RPCConsumer Consumer Error Only Logs - if: always() - continue-on-error: true - run: grep "" testutil/e2e/protocolLogs/06_RPCConsumer* --include="*errors*" - test-sdk-e2e: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: "0" - - - uses: actions/setup-go@v3 - with: - go-version: "1.20.5" - - # Install Node.js - - name: Setup Node.js environment - uses: actions/setup-node@v3 - with: - node-version: "21.2.0" - - - name: Init the SDK - run: GOPATH=~/go ./scripts/init_sdk.sh -s - working-directory: ./ecosystem/lava-sdk - - - name: Build - run: yarn build - working-directory: ./ecosystem/lava-sdk - - - name: Install ts-node - run: npm install -g ts-node - - - name: Install telescope dependencies - run: yarn; yarn e2e-setup - working-directory: ./ecosystem/lavajs - - - name: Setup test environment - run: npm init --yes; npm install --save-dev @types/node - - ###################################################### - ### Run Lava SDK E2E Tests - ###################################################### - - name: Run Lava E2E Tests -timeout 1200s - run: go test ./testutil/e2e/ -run ^TestLavaSDK -v -timeout 1200s # 20mins - - - name: tail -n 300 Lavad Logs - if: always() - run: tail -n 300 testutil/e2e/sdkLogs/00_StartLava.log - - - name: Stake Lava All Logs - if: always() - run: cat testutil/e2e/sdkLogs/01_stakeLava.log - - - name: Stake Lava Error Only Logs - if: always() - continue-on-error: true - run: cat testutil/e2e/sdkLogs/01_stakeLava_errors.log - - - name: head -n 300 JSON Proxy Logs - if: always() - run: head -n 300 testutil/e2e/sdkLogs/02_jsonProxy.log - - - name: tail -n 300 JSON Proxy Logs - if: always() - run: tail -n 300 testutil/e2e/sdkLogs/02_jsonProxy.log - - - name: JSON Proxy Error Only Logs - if: always() - continue-on-error: true - run: cat testutil/e2e/sdkLogs/02_jsonProxy_errors.log - - - name: JSON Provider All Logs - if: always() - run: grep "" testutil/e2e/sdkLogs/03_EthProvider* --exclude="*errors*" - - - name: JSON Provider Error Only Logs - if: always() - continue-on-error: true - run: grep "" testutil/e2e/sdkLogs/03_EthProvider* --include="*errors*" - - - name: Lava Provider All Logs - if: always() - run: grep "" testutil/e2e/sdkLogs/05_LavaProvider* --exclude="*errors*" - - - name: Lava Provider Error Only Logs - if: always() - continue-on-error: true - run: grep "" testutil/e2e/sdkLogs/05_LavaProvider* --include="*errors*" - - - name: Badge Server All Logs - if: always() - run: grep "" testutil/e2e/sdkLogs/01_BadgeServer* --exclude="*errors*" - - - name: Badge Server Error Only Logs - if: always() - continue-on-error: true - run: grep "" testutil/e2e/sdkLogs/01_BadgeServer* --include="*errors*" - - - name: Lava SDK All Logs - if: always() - run: grep "" testutil/e2e/sdkLogs/01_sdkTest* --exclude="*errors*" - - - name: Lava SDK Error Only Logs - if: always() - continue-on-error: true - run: grep "" testutil/e2e/sdkLogs/01_sdkTest* --include="*errors*" - test-payment-e2e: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: "0" - - uses: actions/setup-go@v3 - with: - go-version: 1.20.5 - - ###################################################### - ### Run Lava Protocol Payment E2E Tests - ###################################################### - - name: Run Lava Payment E2E Tests -timeout 1200s - run: go test ./testutil/e2e/ -run ^TestLavaProtocolPayment$ -v -timeout 1200s # 20mins - - - name: tail -n 300 Lavad Logs - if: always() - run: tail -n 300 testutil/e2e/protocolLogs/00_StartLava.log - - - name: Stake Lava All Logs - if: always() - run: cat testutil/e2e/protocolLogs/01_stakeLavaForPayment.log - - - name: Stake Lava Error Only Logs - if: always() - continue-on-error: true - run: cat testutil/e2e/protocolLogs/01_stakeLava_errors.log - - - name: Lava Provider All Logs - if: always() - run: grep "" testutil/e2e/protocolLogs/05_LavaProvider* --exclude="*errors*" - - - name: Lava Provider Error Only Logs - if: always() - continue-on-error: true - run: grep "" testutil/e2e/protocolLogs/05_LavaProvider* --include="*errors*" - - - name: RPCConsumer Consumer All Logs - if: always() - run: grep "" testutil/e2e/protocolLogs/06_RPCConsumer* --exclude="*errors*" - - - name: RPCConsumer Consumer Error Only Logs - if: always() - continue-on-error: true - run: grep "" testutil/e2e/protocolLogs/06_RPCConsumer* --include="*errors*" diff --git a/.github/workflows/lava.yml b/.github/workflows/lava.yml index 6771fe5072..18089a6afa 100644 --- a/.github/workflows/lava.yml +++ b/.github/workflows/lava.yml @@ -13,8 +13,393 @@ concurrency: cancel-in-progress: true jobs: - ci: + test-consensus: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache-dependency-path: go.sum + # Setup Paths + - name: home + run: pwd && ls -l + - name: ls usr + run: ls -l /home/runner/work/lava/lava + - name: cp lava + run: cp -r ~/work/lava/lava ~/go/lava + - name: export PATH + run: export PATH=$PATH:/go:/go/bin:$(go env GOPATH)/bin:/usr/local:`pwd`:/home/runner/work/lava/lava/ + - name: export GOPATH + run: export GOPATH=$GOPATH:$(go env GOPATH):/go:/go/lava:/usr/local:`pwd` + - name: export LAVA + run: export LAVA=/home/runner/work/lava/lava + - name: go env + run: go env + - name: pwd + run: pwd + - name: tree + run: tree + - name: ls -l + run: ls -l + + ###################################################### + ### Run Consensus unitests + ###################################################### + - name: Lava Unit Tests + run: | + go install github.com/jstemmer/go-junit-report/v2@latest + go test -v ./utils/... | go-junit-report -iocopy -set-exit-code -out utils-report.xml + go test -v ./common/... | go-junit-report -iocopy -set-exit-code -out common-report.xml + go test -v ./x/pairing/... | go-junit-report -iocopy -set-exit-code -out pairing-report.xml + go test -v ./x/epochstorage/... | go-junit-report -iocopy -set-exit-code -out epochstorage-report.xml + go test -v ./x/spec/... | go-junit-report -iocopy -set-exit-code -out spec-report.xml + go test -v ./x/conflict/... | go-junit-report -iocopy -set-exit-code -out conflict-report.xml + go test -v ./x/plans/... | go-junit-report -iocopy -set-exit-code -out plans-report.xml + go test -v ./x/projects/... | go-junit-report -iocopy -set-exit-code -out projects-report.xml + go test -v ./x/subscription/... | go-junit-report -iocopy -set-exit-code -out subscription-report.xml + go test -v ./x/dualstaking/... | go-junit-report -iocopy -set-exit-code -out dualstaking-report.xml + go test -v ./x/fixationstore/... | go-junit-report -iocopy -set-exit-code -out fixationstore-report.xml + go test -v ./x/timerstore/... | go-junit-report -iocopy -set-exit-code -out timerstore-report.xml + go test -v ./x/downtime/... | go-junit-report -iocopy -set-exit-code -out downtime-report.xml + go test -v ./x/rewards/... | go-junit-report -iocopy -set-exit-code -out rewards-report.xml + + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: Test Results (Consensus) + path: "*-report.xml" + + test-protocol: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache-dependency-path: go.sum + + # Setup Paths + - name: home + run: pwd && ls -l + - name: ls usr + run: ls -l /home/runner/work/lava/lava + - name: cp lava + run: cp -r ~/work/lava/lava ~/go/lava + - name: export GOPATH + run: export GOPATH=$GOPATH:$(go env GOPATH):/go:/go/lava:/usr/local:`pwd` + - name: export PATH + run: export PATH=$PATH:/go:/go/bin:$(go env GOPATH)/bin:/usr/local:`pwd`:/home/runner/work/lava/lava/:$GOPATH/bin + - name: export LAVA + run: export LAVA=/home/runner/work/lava/lava + - name: go env + run: go env + - name: pwd + run: pwd + - name: tree + run: tree + - name: ls -l + run: ls -l + + ###################################################### + ### Run protocol unitests + ###################################################### + - name: Run Lava Protocol Tests + run: | + go install github.com/jstemmer/go-junit-report/v2@latest + go test -v ./protocol/... | go-junit-report -iocopy -set-exit-code -out protocol-report.xml + go test -v ./ecosystem/cache/... | go-junit-report -iocopy -set-exit-code -out cache-report.xml + + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: Test Results (Protocol) + path: "*-report.xml" + + test-protocol-e2e: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache-dependency-path: go.sum + + ###################################################### + ### Run Lava Protocol E2E Tests + ###################################################### + - name: Run Lava Protocol E2E Tests -timeout 1200s + run: | + go install github.com/jstemmer/go-junit-report/v2@latest + go test ./testutil/e2e/ -run ^TestLavaProtocol$ -v -timeout 1200s | go-junit-report -iocopy -set-exit-code -out protocol-e2e-report.xml # 20mins + + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: Test Results (Protocol E2E) + path: "*-report.xml" + + - name: tail -n 1000 Lavad Logs + if: always() + run: tail -n 1000 testutil/e2e/protocolLogs/00_StartLava.log + + - name: Print all warnings and errors from lavad + continue-on-error: true + if: always() + run: cat testutil/e2e/protocolLogs/00_StartLava.log | grep 'WRN |ERR ' + + - name: Stake Lava All Logs + if: always() + run: cat testutil/e2e/protocolLogs/01_stakeLava.log + + - name: Stake Lava Error Only Logs + if: always() + continue-on-error: true + run: cat testutil/e2e/protocolLogs/01_stakeLava_errors.log + + - name: head -n 300 JSON Proxy Logs + if: always() + run: head -n 300 testutil/e2e/protocolLogs/02_jsonProxy.log + + - name: tail -n 300 JSON Proxy Logs + if: always() + run: tail -n 300 testutil/e2e/protocolLogs/02_jsonProxy.log + + - name: JSON Proxy Error Only Logs + if: always() + continue-on-error: true + run: cat testutil/e2e/protocolLogs/02_jsonProxy_errors.log + + - name: JSON Provider All Logs + if: always() + run: grep "" testutil/e2e/protocolLogs/03_EthProvider* --exclude="*errors*" + + - name: JSON Provider Error Only Logs + if: always() + continue-on-error: true + run: grep "" testutil/e2e/protocolLogs/03_EthProvider* --include="*errors*" + + - name: JSON Consumer All Logs + if: always() + run: grep "" testutil/e2e/protocolLogs/04_jsonConsumer* --exclude="*errors*" + + - name: JSON Consumer Error Only Logs + if: always() + continue-on-error: true + run: grep "" testutil/e2e/protocolLogs/04_jsonConsumer* --include="*errors*" + + - name: Lava Provider All Logs + if: always() + run: grep "" testutil/e2e/protocolLogs/05_LavaProvider* --exclude="*errors*" + + - name: Lava Provider Error Only Logs + if: always() + continue-on-error: true + run: grep "" testutil/e2e/protocolLogs/05_LavaProvider* --include="*errors*" + + - name: Lava over Lava All Logs + if: always() + run: cat testutil/e2e/protocolLogs/07_lavaOverLava.log + + - name: Lava over Lava Error Only Logs + if: always() + continue-on-error: true + run: cat testutil/e2e/protocolLogs/07_lavaOverLava_errors.log + + - name: RPCConsumer Consumer All Logs + if: always() + run: grep "" testutil/e2e/protocolLogs/06_RPCConsumer* --exclude="*errors*" + + - name: RPCConsumer Consumer Error Only Logs + if: always() + continue-on-error: true + run: grep "" testutil/e2e/protocolLogs/06_RPCConsumer* --include="*errors*" + + test-sdk-e2e: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache-dependency-path: go.sum + + # Install Node.js + - name: Setup Node.js environment + uses: actions/setup-node@v4 + with: + node-version: "21.2.0" + + - name: Init the SDK + run: GOPATH=~/go ./scripts/init_sdk.sh -s + working-directory: ./ecosystem/lava-sdk + + - name: Build + run: yarn build + working-directory: ./ecosystem/lava-sdk + + - name: Install ts-node + run: npm install -g ts-node + + - name: Install telescope dependencies + run: yarn; yarn e2e-setup + working-directory: ./ecosystem/lavajs + + - name: Setup test environment + run: npm init --yes; npm install --save-dev @types/node + + ###################################################### + ### Run Lava SDK E2E Tests + ###################################################### + - name: Run Lava SDK E2E Tests -timeout 1200s + run: | + go install github.com/jstemmer/go-junit-report/v2@latest + go test ./testutil/e2e/ -run ^TestLavaSDK -v -timeout 1200s | go-junit-report -iocopy -set-exit-code -out sdk-e2e-report.xml # 20mins + + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: Test Results (SDK E2E) + path: "*-report.xml" + + - name: tail -n 300 Lavad Logs + if: always() + run: tail -n 300 testutil/e2e/sdkLogs/00_StartLava.log + + - name: Stake Lava All Logs + if: always() + run: cat testutil/e2e/sdkLogs/01_stakeLava.log + + - name: Stake Lava Error Only Logs + if: always() + continue-on-error: true + run: cat testutil/e2e/sdkLogs/01_stakeLava_errors.log + + - name: head -n 300 JSON Proxy Logs + if: always() + run: head -n 300 testutil/e2e/sdkLogs/02_jsonProxy.log + + - name: tail -n 300 JSON Proxy Logs + if: always() + run: tail -n 300 testutil/e2e/sdkLogs/02_jsonProxy.log + + - name: JSON Proxy Error Only Logs + if: always() + continue-on-error: true + run: cat testutil/e2e/sdkLogs/02_jsonProxy_errors.log + + - name: JSON Provider All Logs + if: always() + run: grep "" testutil/e2e/sdkLogs/03_EthProvider* --exclude="*errors*" + + - name: JSON Provider Error Only Logs + if: always() + continue-on-error: true + run: grep "" testutil/e2e/sdkLogs/03_EthProvider* --include="*errors*" + + - name: Lava Provider All Logs + if: always() + run: grep "" testutil/e2e/sdkLogs/05_LavaProvider* --exclude="*errors*" + + - name: Lava Provider Error Only Logs + if: always() + continue-on-error: true + run: grep "" testutil/e2e/sdkLogs/05_LavaProvider* --include="*errors*" + + - name: Badge Server All Logs + if: always() + run: grep "" testutil/e2e/sdkLogs/01_BadgeServer* --exclude="*errors*" + + - name: Badge Server Error Only Logs + if: always() + continue-on-error: true + run: grep "" testutil/e2e/sdkLogs/01_BadgeServer* --include="*errors*" + + - name: Lava SDK All Logs + if: always() + run: grep "" testutil/e2e/sdkLogs/01_sdkTest* --exclude="*errors*" + + - name: Lava SDK Error Only Logs + if: always() + continue-on-error: true + run: grep "" testutil/e2e/sdkLogs/01_sdkTest* --include="*errors*" + + test-payment-e2e: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache-dependency-path: go.sum + + ###################################################### + ### Run Lava Protocol Payment E2E Tests + ###################################################### + - name: Run Lava Payment E2E Tests -timeout 1200s + run: | + go install github.com/jstemmer/go-junit-report/v2@latest + go test ./testutil/e2e/ -run ^TestLavaProtocolPayment$ -v -timeout 1200s | go-junit-report -iocopy -set-exit-code -out payment-e2e-report.xml # 20mins + + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: Test Results (Payment E2E) + path: "*-report.xml" + + - name: tail -n 300 Lavad Logs + if: always() + run: tail -n 300 testutil/e2e/protocolLogs/00_StartLava.log + + - name: Stake Lava All Logs + if: always() + run: cat testutil/e2e/protocolLogs/01_stakeLavaForPayment.log + + - name: Stake Lava Error Only Logs + if: always() + continue-on-error: true + run: cat testutil/e2e/protocolLogs/01_stakeLava_errors.log + + - name: Lava Provider All Logs + if: always() + run: grep "" testutil/e2e/protocolLogs/05_LavaProvider* --exclude="*errors*" + + - name: Lava Provider Error Only Logs + if: always() + continue-on-error: true + run: grep "" testutil/e2e/protocolLogs/05_LavaProvider* --include="*errors*" + + - name: RPCConsumer Consumer All Logs + if: always() + run: grep "" testutil/e2e/protocolLogs/06_RPCConsumer* --exclude="*errors*" + + - name: RPCConsumer Consumer Error Only Logs + if: always() + continue-on-error: true + run: grep "" testutil/e2e/protocolLogs/06_RPCConsumer* --include="*errors*" + + report-tests-results: + runs-on: ubuntu-latest + needs: [test-consensus, test-protocol, test-protocol-e2e, test-sdk-e2e, test-payment-e2e] + if: always() + steps: + - name: Download Artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + with: + files: "artifacts/**/*.xml" + + build_and_package: name: ${{ matrix.binary }}-${{ matrix.targetos }}-${{ matrix.arch }} + needs: [test-consensus, test-protocol] runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/lava_sdk_tests.yml b/.github/workflows/lava_sdk_tests.yml index eadf498d89..a13c83c348 100644 --- a/.github/workflows/lava_sdk_tests.yml +++ b/.github/workflows/lava_sdk_tests.yml @@ -1,26 +1,27 @@ name: Lava SDK Tests -on: [pull_request] +on: + pull_request jobs: main: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.yarn key: yarn-${{ hashFiles('yarn.lock') }} restore-keys: yarn- - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v5 with: go-version: "1.20.5" - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: "21.2.0" @@ -33,5 +34,5 @@ jobs: working-directory: ./ecosystem/lava-sdk - name: Test - run: ./node_modules/.bin/jest ./src + run: ./node_modules/.bin/jest ./src --ci working-directory: ./ecosystem/lava-sdk diff --git a/.github/workflows/protocol_tests.yml b/.github/workflows/protocol_tests.yml deleted file mode 100644 index cf63875134..0000000000 --- a/.github/workflows/protocol_tests.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Lava Protocol Tests - -on: [pull_request] - -jobs: - go: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: '0' - - uses: actions/setup-go@v3 - with: - go-version: 1.20.5 - - - # Setup Paths - - name: home - run: pwd && ls -l - - name: ls usr - run: ls -l /home/runner/work/lava/lava - - name: cp lava - run: cp -r ~/work/lava/lava ~/go/lava - - name: export PATH - run: export PATH=$PATH:/go:/go/bin:$(go env GOPATH)/bin:/usr/local:`pwd`:/home/runner/work/lava/lava/ - # - name: export - # run: export PATH=$PATH:/go/lava - - name: export GOPATH - run: export GOPATH=$GOPATH:$(go env GOPATH):/go:/go/lava:/usr/local:`pwd` - - name: export LAVA - run: export LAVA=/home/runner/work/lava/lava - - name: go env - run: go env - - name: pwd - run: pwd - - name: tree - run: tree - - name: ls -l - run: ls -l - - ###################################################### - ### Run protocol unitests - ###################################################### - - name: Run Lava Protocol Tests - run: go test ./protocol/... - - name: Run Cache Tests - run: go test ./ecosystem/cache/... \ No newline at end of file diff --git a/app/app.go b/app/app.go index 208e196e6d..e0fbda2fd2 100644 --- a/app/app.go +++ b/app/app.go @@ -23,6 +23,10 @@ import ( timerstorekeeper "github.com/lavanet/lava/x/timerstore/keeper" timerstoretypes "github.com/lavanet/lava/x/timerstore/types" + "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward" + packetforwardkeeper "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/keeper" + packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/types" + dbm "github.com/cometbft/cometbft-db" abci "github.com/cometbft/cometbft/abci/types" tmjson "github.com/cometbft/cometbft/libs/json" @@ -189,6 +193,7 @@ var Upgrades = []upgrades.Upgrade{ upgrades.Upgrade_1_0_1, upgrades.Upgrade_1_1_0, upgrades.Upgrade_1_2_0, + upgrades.Upgrade_1_3_0, } // this line is used by starport scaffolding # stargate/wasm/app/enabledProposals @@ -236,6 +241,7 @@ var ( crisis.AppModuleBasic{}, slashing.AppModuleBasic{}, feegrantmodule.AppModuleBasic{}, + packetforward.AppModuleBasic{}, ibc.AppModuleBasic{}, ibctm.AppModuleBasic{}, ica.AppModuleBasic{}, @@ -354,7 +360,7 @@ func New( distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, consensusparamtypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, evidencetypes.StoreKey, crisistypes.StoreKey, ibctransfertypes.StoreKey, ibcexported.StoreKey, - icahosttypes.StoreKey, + icahosttypes.StoreKey, packetforwardtypes.StoreKey, icacontrollertypes.StoreKey, capabilitytypes.StoreKey, specmoduletypes.StoreKey, @@ -453,6 +459,17 @@ func New( appCodec, keys[ibcexported.StoreKey], app.GetSubspace(ibcexported.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper, ) + app.PacketForwardKeeper = packetforwardkeeper.NewKeeper( + appCodec, + keys[packetforwardtypes.StoreKey], + nil, // will be zero-value here, reference is set later on with SetTransferKeeper. + app.IBCKeeper.ChannelKeeper, + app.DistrKeeper, + app.BankKeeper, + app.IBCKeeper.ChannelKeeper, + authtypes.NewModuleAddress(govtypes.ModuleName).String(), + ) + // Initialize SpecKeeper prior to govRouter (order is critical) app.SpecKeeper = *specmodulekeeper.NewKeeper( appCodec, @@ -605,12 +622,18 @@ func New( // Create Transfer Keepers app.TransferKeeper = ibctransferkeeper.NewKeeper( - appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName), - app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, - app.AccountKeeper, app.BankKeeper, scopedTransferKeeper, + appCodec, + keys[ibctransfertypes.StoreKey], + app.GetSubspace(ibctransfertypes.ModuleName), + app.PacketForwardKeeper, + app.IBCKeeper.ChannelKeeper, + &app.IBCKeeper.PortKeeper, + app.AccountKeeper, + app.BankKeeper, + scopedTransferKeeper, ) transferModule := transfer.NewAppModule(app.TransferKeeper) - transferIBCModule := transfer.NewIBCModule(app.TransferKeeper) + app.PacketForwardKeeper.SetTransferKeeper(app.TransferKeeper) app.ICAHostKeeper = icahostkeeper.NewKeeper( appCodec, keys[icahosttypes.StoreKey], @@ -678,8 +701,19 @@ func New( // Create static IBC router, add transfer route, then set and seal it ibcRouter := ibcporttypes.NewRouter() - ibcRouter.AddRoute(icahosttypes.SubModuleName, icaHostIBCModule). - AddRoute(ibctransfertypes.ModuleName, transferIBCModule) + ibcRouter.AddRoute(icahosttypes.SubModuleName, icaHostIBCModule) + + var transferStack ibcporttypes.IBCModule + transferStack = transfer.NewIBCModule(app.TransferKeeper) + transferStack = packetforward.NewIBCMiddleware( + transferStack, + app.PacketForwardKeeper, + 0, // retries on timeout + packetforwardkeeper.DefaultForwardTransferPacketTimeoutTimestamp, // forward timeout + packetforwardkeeper.DefaultRefundTransferPacketTimeoutTimestamp, // refund timeout + ) + ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack) + // this line is used by starport scaffolding # ibc/app/router app.IBCKeeper.SetRouter(ibcRouter) @@ -716,6 +750,7 @@ func New( groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), ibc.NewAppModule(app.IBCKeeper), + packetforward.NewAppModule(app.PacketForwardKeeper, app.GetSubspace(packetforwardtypes.ModuleName)), params.NewAppModule(app.ParamsKeeper), transferModule, timerstore.NewAppModule(app.TimerStoreKeeper), @@ -761,6 +796,7 @@ func New( group.ModuleName, authz.ModuleName, icatypes.ModuleName, + packetforwardtypes.ModuleName, specmoduletypes.ModuleName, epochstoragemoduletypes.ModuleName, subscriptionmoduletypes.ModuleName, @@ -790,6 +826,7 @@ func New( group.ModuleName, authz.ModuleName, icatypes.ModuleName, + packetforwardtypes.ModuleName, specmoduletypes.ModuleName, epochstoragemoduletypes.ModuleName, dualstakingmoduletypes.ModuleName, @@ -832,6 +869,7 @@ func New( group.ModuleName, authz.ModuleName, icatypes.ModuleName, + packetforwardtypes.ModuleName, specmoduletypes.ModuleName, subscriptionmoduletypes.ModuleName, downtimemoduletypes.ModuleName, @@ -1102,6 +1140,7 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino paramsKeeper.Subspace(ibcexported.ModuleName) paramsKeeper.Subspace(icacontrollertypes.SubModuleName) paramsKeeper.Subspace(icahosttypes.SubModuleName) + paramsKeeper.Subspace(packetforwardtypes.ModuleName).WithKeyTable(packetforwardtypes.ParamKeyTable()) paramsKeeper.Subspace(specmoduletypes.ModuleName) paramsKeeper.Subspace(epochstoragemoduletypes.ModuleName) paramsKeeper.Subspace(dualstakingmoduletypes.ModuleName) diff --git a/app/keepers/lavaKeepers.go b/app/keepers/lavaKeepers.go index 6483eddb33..231f63b36a 100644 --- a/app/keepers/lavaKeepers.go +++ b/app/keepers/lavaKeepers.go @@ -16,6 +16,7 @@ import ( slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" + packetforwardkeeper "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/keeper" icahostkeeper "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/keeper" ibctransferkeeper "github.com/cosmos/ibc-go/v7/modules/apps/transfer/keeper" ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper" @@ -52,6 +53,8 @@ type LavaKeepers struct { TransferKeeper ibctransferkeeper.Keeper FeeGrantKeeper feegrantkeeper.Keeper + PacketForwardKeeper *packetforwardkeeper.Keeper + // make scoped keepers public for test purposes ScopedIBCKeeper capabilitykeeper.ScopedKeeper ScopedTransferKeeper capabilitykeeper.ScopedKeeper diff --git a/app/upgrades/empty_upgrades.go b/app/upgrades/empty_upgrades.go index afb99ce2b0..78296a2d58 100644 --- a/app/upgrades/empty_upgrades.go +++ b/app/upgrades/empty_upgrades.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/group" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/packetforward/types" icacontrollertypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/types" icahosttypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/host/types" "github.com/lavanet/lava/app/keepers" @@ -235,3 +236,11 @@ var Upgrade_1_2_0 = Upgrade{ CreateUpgradeHandler: defaultUpgradeHandler, StoreUpgrades: store.StoreUpgrades{}, } + +var Upgrade_1_3_0 = Upgrade{ + UpgradeName: "v1.3.0", + CreateUpgradeHandler: defaultUpgradeHandler, + StoreUpgrades: store.StoreUpgrades{ + Added: []string{packetforwardtypes.StoreKey}, + }, +} diff --git a/cookbook/specs/spec_add_namada.json b/cookbook/specs/spec_add_namada.json new file mode 100644 index 0000000000..c3283d1661 --- /dev/null +++ b/cookbook/specs/spec_add_namada.json @@ -0,0 +1,101 @@ +{ + "deposit": "10000000ulava", + "proposal": { + "title": "Add spec: NAMADA SE testnet", + "description": "Adding new specification support for relaying data on NAMADA", + "specs": [ + { + "index": "NAMTSE", + "name": "namada se testnet", + "enabled": true, + "imports": [ + "COSMOSSDK" + ], + "reliability_threshold": 268435455, + "data_reliability_enabled": false, + "block_distance_for_finalized_data": 0, + "blocks_in_finalization_proof": 1, + "average_block_time": 10000, + "allowed_block_lag_for_qos_sync": 2, + "shares": 1, + "min_stake_provider": { + "denom": "ulava", + "amount": "47500000000" + }, + "api_collections": [ + { + "enabled": true, + "collection_data": { + "api_interface": "tendermintrpc", + "internal_path": "", + "type": "", + "add_on": "" + }, + "apis": [], + "headers": [], + "inheritance_apis": [], + "parse_directives": [], + "verifications": [ + { + "name": "chain-id", + "values": [ + { + "expected_value": "shielded-expedition.88f17d1d14" + } + ] + }, + { + "name": "pruning", + "values": [ + { + "latest_distance": 8640 + }, + { + "extension": "archive", + "expected_value": "237907" + } + ] + } + ], + "extensions": [ + { + "name": "archive", + "cu_multiplier": 5, + "rule": { + "block": 8520 + } + } + ] + }, + { + "enabled": false, + "collection_data": { + "api_interface": "rest", + "internal_path": "", + "type": "GET", + "add_on": "" + } + }, + { + "enabled": false, + "collection_data": { + "api_interface": "rest", + "internal_path": "", + "type": "POST", + "add_on": "" + } + }, + { + "enabled": false, + "collection_data": { + "api_interface": "grpc", + "internal_path": "", + "type": "", + "add_on": "" + } + } + ] + } + ] + } +} diff --git a/cookbook/specs/spec_add_near.json b/cookbook/specs/spec_add_near.json index d333ddbd75..6c7d50a57a 100644 --- a/cookbook/specs/spec_add_near.json +++ b/cookbook/specs/spec_add_near.json @@ -226,9 +226,11 @@ "name": "validators", "block_parsing": { "parser_arg": [ + "block_id", + "=", "0" ], - "parser_func": "PARSE_BY_ARG", + "parser_func": "PARSE_DICTIONARY_OR_ORDERED", "default_value": "latest" }, "compute_units": 10, diff --git a/ecosystem/cache/command.go b/ecosystem/cache/command.go index 3d1dbf640b..514e802210 100644 --- a/ecosystem/cache/command.go +++ b/ecosystem/cache/command.go @@ -42,6 +42,7 @@ longer DefaultExpirationForNonFinalized will reduce sync QoS for "latest" reques cacheCmd.Flags().String(FlagLogLevel, zerolog.InfoLevel.String(), "The logging level (trace|debug|info|warn|error|fatal|panic)") cacheCmd.Flags().Duration(ExpirationFlagName, DefaultExpirationTimeFinalized, "how long does a cache entry lasts in the cache for a finalized entry") cacheCmd.Flags().Duration(ExpirationNonFinalizedFlagName, DefaultExpirationForNonFinalized, "how long does a cache entry lasts in the cache for a non finalized entry") + cacheCmd.Flags().Duration(ExpirationNodeErrorsOnFinalizedFlagName, DefaultExpirationNodeErrors, "how long does a cache entry lasts in the cache for a finalized node error entry") cacheCmd.Flags().String(FlagMetricsAddress, DisabledFlagOption, "address to listen to prometheus metrics 127.0.0.1:5555, later you can curl http://127.0.0.1:5555/metrics") cacheCmd.Flags().Int64(FlagCacheSizeName, 2*1024*1024*1024, "the maximal amount of entries to save") return cacheCmd diff --git a/ecosystem/cache/handlers.go b/ecosystem/cache/handlers.go index 54c6e21de9..d3c6b34db2 100644 --- a/ecosystem/cache/handlers.go +++ b/ecosystem/cache/handlers.go @@ -263,11 +263,17 @@ func (s *RelayerCacheServer) SetRelay(ctx context.Context, relayCacheSet *pairin utils.Attribute{Key: "requested_block", Value: relayCacheSet.RequestedBlock}, utils.Attribute{Key: "response_data", Value: parser.CapStringLen(string(relayCacheSet.Response.Data))}, utils.Attribute{Key: "requestHash", Value: string(relayCacheSet.BlockHash)}, - utils.Attribute{Key: "latestKnownBlock", Value: string(relayCacheSet.BlockHash)}) + utils.Attribute{Key: "latestKnownBlock", Value: string(relayCacheSet.BlockHash)}, + utils.Attribute{Key: "IsNodeError", Value: relayCacheSet.IsNodeError}, + ) // finalized entries can stay there if relayCacheSet.Finalized { cache := s.CacheServer.finalizedCache - cache.SetWithTTL(cacheKey, cacheValue, cacheValue.Cost(), s.CacheServer.ExpirationFinalized) + if relayCacheSet.IsNodeError { + cache.SetWithTTL(cacheKey, cacheValue, cacheValue.Cost(), s.CacheServer.ExpirationNodeErrors) + } else { + cache.SetWithTTL(cacheKey, cacheValue, cacheValue.Cost(), s.CacheServer.ExpirationFinalized) + } } else { cache := s.CacheServer.tempCache cache.SetWithTTL(cacheKey, cacheValue, cacheValue.Cost(), s.getExpirationForChain(time.Duration(relayCacheSet.AverageBlockTime), relayCacheSet.BlockHash)) diff --git a/ecosystem/cache/server.go b/ecosystem/cache/server.go index 69bc0eb0a4..b7dd43b862 100644 --- a/ecosystem/cache/server.go +++ b/ecosystem/cache/server.go @@ -23,12 +23,14 @@ import ( ) const ( - ExpirationFlagName = "expiration" - ExpirationNonFinalizedFlagName = "expiration-non-finalized" - FlagCacheSizeName = "max-items" - DefaultExpirationForNonFinalized = 500 * time.Millisecond - DefaultExpirationTimeFinalized = time.Hour - CacheNumCounters = 100000000 // expect 10M items + ExpirationFlagName = "expiration" + ExpirationNonFinalizedFlagName = "expiration-non-finalized" + ExpirationNodeErrorsOnFinalizedFlagName = "expiration-finalized-node-errors" + FlagCacheSizeName = "max-items" + DefaultExpirationForNonFinalized = 500 * time.Millisecond + DefaultExpirationTimeFinalized = time.Hour + DefaultExpirationNodeErrors = 5 * time.Second + CacheNumCounters = 100000000 // expect 10M items ) type CacheServer struct { @@ -36,6 +38,7 @@ type CacheServer struct { tempCache *ristretto.Cache ExpirationFinalized time.Duration ExpirationNonFinalized time.Duration + ExpirationNodeErrors time.Duration CacheMetrics *CacheMetrics CacheMaxCost int64 } diff --git a/go.mod b/go.mod index d60e12db9f..c42ea5ac36 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/cometbft/cometbft-db v0.8.0 github.com/confio/ics23/go v0.9.0 // indirect github.com/cosmos/cosmos-sdk v0.47.10 - github.com/cosmos/ibc-go/v7 v7.2.0 + github.com/cosmos/ibc-go/v7 v7.3.1 github.com/ethereum/go-ethereum v1.10.18 github.com/gofiber/fiber/v2 v2.50.0 github.com/gofiber/websocket/v2 v2.0.22 @@ -30,6 +30,7 @@ require ( cosmossdk.io/math v1.3.0 github.com/cosmos/cosmos-proto v1.0.0-beta.4 github.com/cosmos/gogoproto v1.4.10 + github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 github.com/dgraph-io/badger/v4 v4.1.0 github.com/fullstorydev/grpcurl v1.8.5 github.com/gogo/status v1.1.0 @@ -91,6 +92,7 @@ require ( github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/huandu/skiplist v1.2.0 // indirect + github.com/iancoleman/orderedmap v0.2.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect diff --git a/go.sum b/go.sum index 6e333515c4..336e3a2818 100644 --- a/go.sum +++ b/go.sum @@ -403,8 +403,10 @@ github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoK github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= github.com/cosmos/iavl v0.20.1 h1:rM1kqeG3/HBT85vsZdoSNsehciqUQPWrR4BYmqE2+zg= github.com/cosmos/iavl v0.20.1/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= -github.com/cosmos/ibc-go/v7 v7.2.0 h1:dx0DLUl7rxdyZ8NiT6UsrbzKOJx/w7s+BOaewFRH6cg= -github.com/cosmos/ibc-go/v7 v7.2.0/go.mod h1:OOcjKIRku/j1Xs1RgKK0yvKRrJ5iFuZYMetR1n3yMlc= +github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 h1:MZGDMETv72suFpTAD6VPGqSIm1FJcChtk2HmVh9D+Bo= +github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3/go.mod h1:UvDmcGIWJPIytq+Q78/ff5NTOsuX/7IrNgEugTW5i0s= +github.com/cosmos/ibc-go/v7 v7.3.1 h1:bil1IjnHdyWDASFYKfwdRiNtFP6WK3osW7QFEAgU4I8= +github.com/cosmos/ibc-go/v7 v7.3.1/go.mod h1:wvx4pPBofe5ZdMNV3OFRxSI4auEP5Qfqf8JXLLNV04g= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= github.com/cosmos/ics23/go v0.10.0/go.mod h1:ZfJSmng/TBNTBkFemHHHj5YY7VAU/MBU980F4VU1NG0= github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5saFCr7pDnw= @@ -798,6 +800,8 @@ github.com/huin/goupnp v1.0.3-0.20220313090229-ca81a64b4204/go.mod h1:ZxNlw5WqJj github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= +github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= diff --git a/proto/lavanet/lava/pairing/relayCache.proto b/proto/lavanet/lava/pairing/relayCache.proto index 8ad1e37387..28ddd120ee 100644 --- a/proto/lavanet/lava/pairing/relayCache.proto +++ b/proto/lavanet/lava/pairing/relayCache.proto @@ -50,4 +50,5 @@ message RelayCacheSet { string chain_id = 9; // used to set latest block per chain. int64 seen_block = 10; int64 average_block_time = 11; + bool is_node_error = 12; // node errors wont be cached for long even if they are finalized in cases where it returns a valid response later on } \ No newline at end of file diff --git a/protocol/chainlib/base_chain_parser.go b/protocol/chainlib/base_chain_parser.go index 301f210ffc..d25e9f175b 100644 --- a/protocol/chainlib/base_chain_parser.go +++ b/protocol/chainlib/base_chain_parser.go @@ -22,6 +22,7 @@ type PolicyInf interface { } type BaseChainParser struct { + internalPaths map[string]struct{} taggedApis map[spectypes.FUNCTION_TAG]TaggedContainer spec spectypes.Spec rwLock sync.RWMutex @@ -226,11 +227,12 @@ func (bcp *BaseChainParser) GetVerifications(supported []string) (retVerificatio return } -func (bcp *BaseChainParser) Construct(spec spectypes.Spec, taggedApis map[spectypes.FUNCTION_TAG]TaggedContainer, +func (bcp *BaseChainParser) Construct(spec spectypes.Spec, internalPaths map[string]struct{}, taggedApis map[spectypes.FUNCTION_TAG]TaggedContainer, serverApis map[ApiKey]ApiContainer, apiCollections map[CollectionKey]*spectypes.ApiCollection, headers map[ApiKey]*spectypes.Header, verifications map[VerificationKey][]VerificationContainer, extensionParser extensionslib.ExtensionParser, ) { bcp.spec = spec + bcp.internalPaths = internalPaths bcp.serverApis = serverApis bcp.taggedApis = taggedApis bcp.headers = headers @@ -282,7 +284,7 @@ func (bcp *BaseChainParser) extensionParsingInner(addon string, parsedMessageArg } // getSupportedApi fetches service api from spec by name -func (apip *BaseChainParser) getSupportedApi(name, connectionType string) (*ApiContainer, error) { +func (apip *BaseChainParser) getSupportedApi(apiKey ApiKey) (*ApiContainer, error) { // Guard that the GrpcChainParser instance exists if apip == nil { return nil, errors.New("ChainParser not defined") @@ -293,10 +295,7 @@ func (apip *BaseChainParser) getSupportedApi(name, connectionType string) (*ApiC defer apip.rwLock.RUnlock() // Fetch server api by name - apiCont, ok := apip.serverApis[ApiKey{ - Name: name, - ConnectionType: connectionType, - }] + apiCont, ok := apip.serverApis[apiKey] // Return an error if spec does not exist if !ok { @@ -305,12 +304,20 @@ func (apip *BaseChainParser) getSupportedApi(name, connectionType string) (*ApiC // Return an error if api is disabled if !apiCont.api.Enabled { - return nil, utils.LavaFormatInfo("api is disabled", utils.Attribute{Key: "name", Value: name}, utils.Attribute{Key: "connectionType", Value: connectionType}) + return nil, utils.LavaFormatInfo("api is disabled", utils.Attribute{Key: "apiKey", Value: apiKey}) } return &apiCont, nil } +func (apip *BaseChainParser) isValidInternalPath(path string) bool { + if apip == nil || len(apip.internalPaths) == 0 { + return false + } + _, ok := apip.internalPaths[path] + return ok +} + // getSupportedApi fetches service api from spec by name func (apip *BaseChainParser) getApiCollection(connectionType, internalPath, addon string) (*spectypes.ApiCollection, error) { // Guard that the GrpcChainParser instance exists @@ -342,7 +349,8 @@ func (apip *BaseChainParser) getApiCollection(connectionType, internalPath, addo return api, nil } -func getServiceApis(spec spectypes.Spec, rpcInterface string) (retServerApis map[ApiKey]ApiContainer, retTaggedApis map[spectypes.FUNCTION_TAG]TaggedContainer, retApiCollections map[CollectionKey]*spectypes.ApiCollection, retHeaders map[ApiKey]*spectypes.Header, retVerifications map[VerificationKey][]VerificationContainer) { +func getServiceApis(spec spectypes.Spec, rpcInterface string) (retInternalPaths map[string]struct{}, retServerApis map[ApiKey]ApiContainer, retTaggedApis map[spectypes.FUNCTION_TAG]TaggedContainer, retApiCollections map[CollectionKey]*spectypes.ApiCollection, retHeaders map[ApiKey]*spectypes.Header, retVerifications map[VerificationKey][]VerificationContainer) { + retInternalPaths = map[string]struct{}{} serverApis := map[ApiKey]ApiContainer{} taggedApis := map[spectypes.FUNCTION_TAG]TaggedContainer{} headers := map[ApiKey]*spectypes.Header{} @@ -361,6 +369,10 @@ func getServiceApis(spec spectypes.Spec, rpcInterface string) (retServerApis map InternalPath: apiCollection.CollectionData.InternalPath, Addon: apiCollection.CollectionData.AddOn, } + + // add as a valid internal path + retInternalPaths[apiCollection.CollectionData.InternalPath] = struct{}{} + for _, parsing := range apiCollection.ParseDirectives { taggedApis[parsing.FunctionTag] = TaggedContainer{ Parsing: parsing, @@ -387,12 +399,34 @@ func getServiceApis(spec spectypes.Spec, rpcInterface string) (retServerApis map collectionKey: collectionKey, } } else { - serverApis[ApiKey{ - Name: api.Name, - ConnectionType: collectionKey.ConnectionType, - }] = ApiContainer{ - api: api, - collectionKey: collectionKey, + // add another internal path entry so it can specifically be referenced + if apiCollection.CollectionData.InternalPath != "" { + serverApis[ApiKey{ + Name: api.Name, + ConnectionType: collectionKey.ConnectionType, + InternalPath: apiCollection.CollectionData.InternalPath, + }] = ApiContainer{ + api: api, + collectionKey: collectionKey, + } + // if it does not exist set it + if _, ok := serverApis[ApiKey{Name: api.Name, ConnectionType: collectionKey.ConnectionType}]; !ok { + serverApis[ApiKey{ + Name: api.Name, + ConnectionType: collectionKey.ConnectionType, + }] = ApiContainer{ + api: api, + collectionKey: collectionKey, + } + } + } else { + serverApis[ApiKey{ + Name: api.Name, + ConnectionType: collectionKey.ConnectionType, + }] = ApiContainer{ + api: api, + collectionKey: collectionKey, + } } } } @@ -438,7 +472,7 @@ func getServiceApis(spec spectypes.Spec, rpcInterface string) (retServerApis map apiCollections[collectionKey] = apiCollection } } - return serverApis, taggedApis, apiCollections, headers, verifications + return retInternalPaths, serverApis, taggedApis, apiCollections, headers, verifications } func (bcp *BaseChainParser) ExtensionsParser() *extensionslib.ExtensionParser { diff --git a/protocol/chainlib/chain_fetcher.go b/protocol/chainlib/chain_fetcher.go index eeb2597013..e6873ca5cc 100644 --- a/protocol/chainlib/chain_fetcher.go +++ b/protocol/chainlib/chain_fetcher.go @@ -169,8 +169,11 @@ func (cf *ChainFetcher) Verify(ctx context.Context, verification VerificationCon if err != nil { return utils.LavaFormatWarning("[-] verify failed sending chainMessage", err, []utils.Attribute{{Key: "chainID", Value: cf.endpoint.ChainID}, {Key: "APIInterface", Value: cf.endpoint.ApiInterface}}...) } + if reply == nil || reply.RelayReply == nil { + return utils.LavaFormatWarning("[-] verify failed sending chainMessage, reply or reply.RelayReply are nil", nil, []utils.Attribute{{Key: "chainID", Value: cf.endpoint.ChainID}, {Key: "APIInterface", Value: cf.endpoint.ApiInterface}}...) + } - parserInput, err := FormatResponseForParsing(reply, chainMessage) + parserInput, err := FormatResponseForParsing(reply.RelayReply, chainMessage) if err != nil { return utils.LavaFormatWarning("[-] verify failed to parse result", err, utils.LogAttr("chain_id", chainId), @@ -184,7 +187,7 @@ func (cf *ChainFetcher) Verify(ctx context.Context, verification VerificationCon {Key: "chainId", Value: chainId}, {Key: "nodeUrl", Value: proxyUrl.Url}, {Key: "Method", Value: parsing.GetApiName()}, - {Key: "Response", Value: string(reply.Data)}, + {Key: "Response", Value: string(reply.RelayReply.Data)}, }...) } if verification.LatestDistance != 0 && latestBlock != 0 && verification.ParseDirective.FunctionTag != spectypes.FUNCTION_TAG_GET_BLOCK_BY_NUM { @@ -194,7 +197,7 @@ func (cf *ChainFetcher) Verify(ctx context.Context, verification VerificationCon {Key: "chainId", Value: chainId}, {Key: "nodeUrl", Value: proxyUrl.Url}, {Key: "Method", Value: parsing.GetApiName()}, - {Key: "Response", Value: string(reply.Data)}, + {Key: "Response", Value: string(reply.RelayReply.Data)}, {Key: "parsedResult", Value: parsedResult}, }...) } @@ -271,13 +274,13 @@ func (cf *ChainFetcher) FetchLatestBlockNum(ctx context.Context) (int64, error) if err != nil { return spectypes.NOT_APPLICABLE, utils.LavaFormatDebug(tagName+" failed sending chainMessage", []utils.Attribute{{Key: "chainID", Value: cf.endpoint.ChainID}, {Key: "APIInterface", Value: cf.endpoint.ApiInterface}, {Key: "error", Value: err}}...) } - parserInput, err := FormatResponseForParsing(reply, chainMessage) + parserInput, err := FormatResponseForParsing(reply.RelayReply, chainMessage) if err != nil { return spectypes.NOT_APPLICABLE, utils.LavaFormatDebug(tagName+" Failed formatResponseForParsing", []utils.Attribute{ {Key: "chainId", Value: chainId}, {Key: "nodeUrl", Value: proxyUrl.Url}, {Key: "Method", Value: parsing.ApiName}, - {Key: "Response", Value: string(reply.Data)}, + {Key: "Response", Value: string(reply.RelayReply.Data)}, {Key: "error", Value: err}, }...) } @@ -287,7 +290,7 @@ func (cf *ChainFetcher) FetchLatestBlockNum(ctx context.Context) (int64, error) {Key: "chainId", Value: chainId}, {Key: "nodeUrl", Value: proxyUrl.Url}, {Key: "Method", Value: parsing.ApiName}, - {Key: "Response", Value: string(reply.Data)}, + {Key: "Response", Value: string(reply.RelayReply.Data)}, {Key: "error", Value: err}, }...) } @@ -331,14 +334,14 @@ func (cf *ChainFetcher) FetchBlockHashByNum(ctx context.Context, blockNum int64) timeTaken := time.Since(start) return "", utils.LavaFormatDebug(tagName+" failed sending chainMessage", []utils.Attribute{{Key: "sendTime", Value: timeTaken}, {Key: "error", Value: err}, {Key: "chainID", Value: cf.endpoint.ChainID}, {Key: "APIInterface", Value: cf.endpoint.ApiInterface}}...) } - parserInput, err := FormatResponseForParsing(reply, chainMessage) + parserInput, err := FormatResponseForParsing(reply.RelayReply, chainMessage) if err != nil { return "", utils.LavaFormatDebug(tagName+" Failed formatResponseForParsing", []utils.Attribute{ {Key: "error", Value: err}, {Key: "chainId", Value: chainId}, {Key: "nodeUrl", Value: proxyUrl.Url}, {Key: "Method", Value: parsing.ApiName}, - {Key: "Response", Value: string(reply.Data)}, + {Key: "Response", Value: string(reply.RelayReply.Data)}, }...) } @@ -349,14 +352,14 @@ func (cf *ChainFetcher) FetchBlockHashByNum(ctx context.Context, blockNum int64) {Key: "chainId", Value: chainId}, {Key: "nodeUrl", Value: proxyUrl.Url}, {Key: "Method", Value: parsing.ApiName}, - {Key: "Response", Value: string(reply.Data)}, + {Key: "Response", Value: string(reply.RelayReply.Data)}, }...) } _, _, blockDistanceToFinalization, _ := cf.chainParser.ChainBlockStats() latestBlock := atomic.LoadInt64(&cf.latestBlock) // assuming FetchLatestBlockNum is called before this one it's always true if latestBlock > 0 { finalized := spectypes.IsFinalizedBlock(blockNum, latestBlock, int64(blockDistanceToFinalization)) - cf.populateCache(cf.constructRelayData(collectionData.Type, path, data, blockNum, "", nil, latestBlock), reply, []byte(res), finalized) + cf.populateCache(cf.constructRelayData(collectionData.Type, path, data, blockNum, "", nil, latestBlock), reply.RelayReply, []byte(res), finalized) } return res, nil } diff --git a/protocol/chainlib/chain_router.go b/protocol/chainlib/chain_router.go index d50ca93b0a..0b0f73cb47 100644 --- a/protocol/chainlib/chain_router.go +++ b/protocol/chainlib/chain_router.go @@ -8,7 +8,6 @@ import ( "github.com/lavanet/lava/protocol/common" "github.com/lavanet/lava/protocol/lavasession" "github.com/lavanet/lava/utils" - pairingtypes "github.com/lavanet/lava/x/pairing/types" ) type chainRouterEntry struct { @@ -59,7 +58,7 @@ func (cri chainRouterImpl) ExtensionsSupported(extensions []string) bool { return ok } -func (cri chainRouterImpl) SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend, extensions []string) (relayReply *pairingtypes.RelayReply, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, proxyUrl common.NodeUrl, chainId string, err error) { +func (cri chainRouterImpl) SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend, extensions []string) (relayReply *RelayReplyWrapper, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, proxyUrl common.NodeUrl, chainId string, err error) { // add the parsed addon from the apiCollection addon := chainMessage.GetApiCollection().CollectionData.AddOn selectedChainProxy, err := cri.getChainProxySupporting(addon, extensions) diff --git a/protocol/chainlib/chainlib.go b/protocol/chainlib/chainlib.go index 5be294391c..597b82e44f 100644 --- a/protocol/chainlib/chainlib.go +++ b/protocol/chainlib/chainlib.go @@ -113,13 +113,13 @@ type ChainListener interface { } type ChainRouter interface { - SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend, extensions []string) (relayReply *pairingtypes.RelayReply, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, proxyUrl common.NodeUrl, chainId string, err error) // has to be thread safe, reuse code within ParseMsg as common functionality + SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend, extensions []string) (relayReply *RelayReplyWrapper, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, proxyUrl common.NodeUrl, chainId string, err error) // has to be thread safe, reuse code within ParseMsg as common functionality ExtensionsSupported([]string) bool } type ChainProxy interface { GetChainProxyInformation() (common.NodeUrl, string) - SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *pairingtypes.RelayReply, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) // has to be thread safe, reuse code within ParseMsg as common functionality + SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *RelayReplyWrapper, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) // has to be thread safe, reuse code within ParseMsg as common functionality } func GetChainRouter(ctx context.Context, nConns uint, rpcProviderEndpoint *lavasession.RPCProviderEndpoint, chainParser ChainParser) (ChainRouter, error) { diff --git a/protocol/chainlib/chainproxy/rpcclient/http.go b/protocol/chainlib/chainproxy/rpcclient/http.go index 87640cd6f0..1d5c230730 100755 --- a/protocol/chainlib/chainproxy/rpcclient/http.go +++ b/protocol/chainlib/chainproxy/rpcclient/http.go @@ -203,6 +203,7 @@ func (hc *httpConn) doRequest(ctx context.Context, msg interface{}, isJsonRPC bo resp, err := hc.client.Do(req) if resp != nil { // resp can be non nil on error + metadata.AppendToOutgoingContext(ctx, common.StatusCodeMetadataKey, strconv.Itoa(resp.StatusCode)) trailer := metadata.Pairs(common.StatusCodeMetadataKey, strconv.Itoa(resp.StatusCode)) grpc.SetTrailer(ctx, trailer) // we ignore this error here since this code can be triggered not from grpc } diff --git a/protocol/chainlib/common.go b/protocol/chainlib/common.go index 0a80764713..382a63712e 100644 --- a/protocol/chainlib/common.go +++ b/protocol/chainlib/common.go @@ -31,6 +31,11 @@ const ( var InvalidResponses = []string{"null", "", "nil", "undefined"} +type RelayReplyWrapper struct { + StatusCode int + RelayReply *pairingtypes.RelayReply +} + type VerificationKey struct { Extension string Addon string @@ -66,6 +71,7 @@ type ApiContainer struct { type ApiKey struct { Name string ConnectionType string + InternalPath string } type CollectionKey struct { diff --git a/protocol/chainlib/common_test.go b/protocol/chainlib/common_test.go index 235b1c4716..9f8c6680dc 100644 --- a/protocol/chainlib/common_test.go +++ b/protocol/chainlib/common_test.go @@ -384,7 +384,7 @@ func TestGetServiceApis(t *testing.T) { } rpcInterface := spectypes.APIInterfaceRest - serverApis, _, _, _, _ := getServiceApis(spec, rpcInterface) + _, serverApis, _, _, _, _ := getServiceApis(spec, rpcInterface) // Test serverApis if len(serverApis) != 3 { diff --git a/protocol/chainlib/grpc.go b/protocol/chainlib/grpc.go index c71161d756..4606762a48 100644 --- a/protocol/chainlib/grpc.go +++ b/protocol/chainlib/grpc.go @@ -42,6 +42,8 @@ import ( "google.golang.org/grpc/status" ) +const GRPCStatusCodeOnFailedMessages = 32 + type GrpcNodeErrorResponse struct { ErrorMessage string `json:"error_message"` ErrorCode uint32 `json:"error_code"` @@ -94,7 +96,8 @@ func (apip *GrpcChainParser) getSupportedApi(name, connectionType string) (*ApiC if apip == nil { return nil, errors.New("ChainParser not defined") } - return apip.BaseChainParser.getSupportedApi(name, connectionType) + apiKey := ApiKey{Name: name, ConnectionType: connectionType} + return apip.BaseChainParser.getSupportedApi(apiKey) } func (apip *GrpcChainParser) setupForConsumer(relayer grpcproxy.ProxyCallBack) { @@ -217,8 +220,8 @@ func (apip *GrpcChainParser) SetSpec(spec spectypes.Spec) { defer apip.rwLock.Unlock() // extract server and tagged apis from spec - serverApis, taggedApis, apiCollections, headers, verifications := getServiceApis(spec, spectypes.APIInterfaceGrpc) - apip.BaseChainParser.Construct(spec, taggedApis, serverApis, apiCollections, headers, verifications, apip.BaseChainParser.extensionParser) + internalPaths, serverApis, taggedApis, apiCollections, headers, verifications := getServiceApis(spec, spectypes.APIInterfaceGrpc) + apip.BaseChainParser.Construct(spec, internalPaths, taggedApis, serverApis, apiCollections, headers, verifications, apip.BaseChainParser.extensionParser) } // DataReliabilityParams returns data reliability params from spec (spec.enabled and spec.dataReliabilityThreshold) @@ -426,7 +429,7 @@ func newGrpcChainProxy(ctx context.Context, averageBlockTime time.Duration, pars return cp, nil } -func (cp *GrpcChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *pairingtypes.RelayReply, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { +func (cp *GrpcChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *RelayReplyWrapper, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { if ch != nil { return nil, "", nil, utils.LavaFormatError("Subscribe is not allowed on grpc", nil, utils.Attribute{Key: "GUID", Value: ctx}) } @@ -530,6 +533,21 @@ func (cp *GrpcChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, connectCtx, cancel := cp.CapTimeoutForSend(ctx, chainMessage) defer cancel() err = conn.Invoke(connectCtx, "/"+nodeMessage.Path, msg, response, grpc.Header(&respHeaders)) + // Extract status code from response headers + statusCodeHeader := respHeaders.Get("grpc-status") + if len(statusCodeHeader) > 0 { + statusCodeTest, err := strconv.Atoi(statusCodeHeader[0]) + if err != nil { + // Handle error + utils.LavaFormatError("Error:", err, utils.LogAttr("statusCode", statusCodeTest)) + } else { + // Use the status code + utils.LavaFormatDebug("Status Code:", utils.LogAttr("statusCode", statusCodeTest)) + } + } else { + utils.LavaFormatDebug("NO Status Code:") + // No status code found in response headers + } if err != nil { // Validate if the error is related to the provider connection to the node or it is a valid error // in case the error is valid (e.g. bad input parameters) the error will return in the form of a valid error reply @@ -537,13 +555,16 @@ func (cp *GrpcChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, return nil, "", nil, parsedError } // return the node's error back to the client as the error type is a invalid request which is cu deductible - respBytes, handlingError := parseGrpcNodeErrorToReply(ctx, err) + respBytes, statusCode, handlingError := parseGrpcNodeErrorToReply(ctx, err) if handlingError != nil { return nil, "", nil, handlingError } - reply := &pairingtypes.RelayReply{ - Data: respBytes, - Metadata: convertToMetadataMapOfSlices(respHeaders), + reply := &RelayReplyWrapper{ + StatusCode: int(statusCode), + RelayReply: &pairingtypes.RelayReply{ + Data: respBytes, + Metadata: convertToMetadataMapOfSlices(respHeaders), + }, } return reply, "", nil, nil } @@ -553,10 +574,12 @@ func (cp *GrpcChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, if err != nil { return nil, "", nil, utils.LavaFormatError("proto.Marshal(response) Failed", err, utils.Attribute{Key: "GUID", Value: ctx}) } - - reply := &pairingtypes.RelayReply{ - Data: respBytes, - Metadata: convertToMetadataMapOfSlices(respHeaders), + reply := &RelayReplyWrapper{ + StatusCode: http.StatusOK, // status code is used only for rest at the moment + RelayReply: &pairingtypes.RelayReply{ + Data: respBytes, + Metadata: convertToMetadataMapOfSlices(respHeaders), + }, } return reply, "", nil, nil } @@ -564,21 +587,24 @@ func (cp *GrpcChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, // This method assumes that the error is due to misuse of the request arguments, meaning the user would like to get // the response from the server to fix the request arguments. this method will make sure the user will get the response // from the node in the same format as expected. -func parseGrpcNodeErrorToReply(ctx context.Context, err error) ([]byte, error) { +func parseGrpcNodeErrorToReply(ctx context.Context, err error) ([]byte, uint32, error) { var respBytes []byte var marshalingError error + var errorCode uint32 = GRPCStatusCodeOnFailedMessages + // try fetching status code from error or otherwise use the GRPCStatusCodeOnFailedMessages if statusError, ok := status.FromError(err); ok { - respBytes, marshalingError = json.Marshal(&GrpcNodeErrorResponse{ErrorMessage: statusError.Message(), ErrorCode: uint32(statusError.Code())}) + errorCode = uint32(statusError.Code()) + respBytes, marshalingError = json.Marshal(&GrpcNodeErrorResponse{ErrorMessage: statusError.Message(), ErrorCode: errorCode}) if marshalingError != nil { - return nil, utils.LavaFormatError("json.Marshal(&GrpcNodeErrorResponse Failed 1", err, utils.Attribute{Key: "GUID", Value: ctx}) + return nil, errorCode, utils.LavaFormatError("json.Marshal(&GrpcNodeErrorResponse Failed 1", err, utils.Attribute{Key: "GUID", Value: ctx}) } } else { - respBytes, marshalingError = json.Marshal(&GrpcNodeErrorResponse{ErrorMessage: err.Error(), ErrorCode: uint32(32)}) + respBytes, marshalingError = json.Marshal(&GrpcNodeErrorResponse{ErrorMessage: err.Error(), ErrorCode: errorCode}) if marshalingError != nil { - return nil, utils.LavaFormatError("json.Marshal(&GrpcNodeErrorResponse Failed 2", err, utils.Attribute{Key: "GUID", Value: ctx}) + return nil, errorCode, utils.LavaFormatError("json.Marshal(&GrpcNodeErrorResponse Failed 2", err, utils.Attribute{Key: "GUID", Value: ctx}) } } - return respBytes, nil + return respBytes, errorCode, nil } func marshalJSON(msg proto.Message) ([]byte, error) { diff --git a/protocol/chainlib/grpc_test.go b/protocol/chainlib/grpc_test.go index d5404435c7..23f770c1fe 100644 --- a/protocol/chainlib/grpc_test.go +++ b/protocol/chainlib/grpc_test.go @@ -214,7 +214,7 @@ func TestParsingRequestedBlocksHeadersGrpc(t *testing.T) { require.Equal(t, test.requestedBlock, requestedBlock) reply, _, _, _, _, err := chainRouter.SendNodeMsg(ctx, nil, chainMessage, nil) require.NoError(t, err) - parserInput, err := FormatResponseForParsing(reply, chainMessage) + parserInput, err := FormatResponseForParsing(reply.RelayReply, chainMessage) require.NoError(t, err) blockNum, err := parser.ParseBlockFromReply(parserInput, parsingForCrafting.ResultParsing) require.NoError(t, err) @@ -283,7 +283,7 @@ func TestSettingBlocksHeadersGrpc(t *testing.T) { require.Equal(t, test.block, requestedBlock) reply, _, _, _, _, err := chainRouter.SendNodeMsg(ctx, nil, chainMessage, nil) require.NoError(t, err) - parserInput, err := FormatResponseForParsing(reply, chainMessage) + parserInput, err := FormatResponseForParsing(reply.RelayReply, chainMessage) require.NoError(t, err) blockNum, err := parser.ParseBlockFromReply(parserInput, parsingForCrafting.ResultParsing) require.NoError(t, err) diff --git a/protocol/chainlib/jsonRPC.go b/protocol/chainlib/jsonRPC.go index 00b1b6e436..dcdd78d099 100644 --- a/protocol/chainlib/jsonRPC.go +++ b/protocol/chainlib/jsonRPC.go @@ -47,12 +47,13 @@ func (apip *JsonRPCChainParser) getApiCollection(connectionType, internalPath, a return apip.BaseChainParser.getApiCollection(connectionType, internalPath, addon) } -func (apip *JsonRPCChainParser) getSupportedApi(name, connectionType string) (*ApiContainer, error) { +func (apip *JsonRPCChainParser) getSupportedApi(name, connectionType string, internalPath string) (*ApiContainer, error) { // Guard that the JsonRPCChainParser instance exists if apip == nil { return nil, errors.New("ChainParser not defined") } - return apip.BaseChainParser.getSupportedApi(name, connectionType) + apiKey := ApiKey{Name: name, ConnectionType: connectionType, InternalPath: internalPath} + return apip.BaseChainParser.getSupportedApi(apiKey) } func (apip *JsonRPCChainParser) CraftMessage(parsing *spectypes.ParseDirective, connectionType string, craftData *CraftData, metadata []pairingtypes.Metadata) (ChainMessageForSend, error) { @@ -71,7 +72,7 @@ func (apip *JsonRPCChainParser) CraftMessage(parsing *spectypes.ParseDirective, Params: nil, BaseMessage: chainproxy.BaseMessage{Headers: metadata}, } - apiCont, err := apip.getSupportedApi(parsing.ApiName, connectionType) + apiCont, err := apip.getSupportedApi(parsing.ApiName, connectionType, "") if err != nil { return nil, err } @@ -103,8 +104,12 @@ func (apip *JsonRPCChainParser) ParseMsg(url string, data []byte, connectionType var latestRequestedBlock, earliestRequestedBlock int64 = 0, 0 for idx, msg := range msgs { var requestedBlockForMessage int64 + internalPath := "" + if apip.isValidInternalPath(url) { + internalPath = url + } // Check api is supported and save it in nodeMsg - apiCont, err := apip.getSupportedApi(msg.Method, connectionType) + apiCont, err := apip.getSupportedApi(msg.Method, connectionType, internalPath) if err != nil { utils.LavaFormatInfo("getSupportedApi jsonrpc failed", utils.LogAttr("method", msg.Method), utils.LogAttr("error", err)) return nil, err @@ -232,8 +237,8 @@ func (apip *JsonRPCChainParser) SetSpec(spec spectypes.Spec) { defer apip.rwLock.Unlock() // extract server and tagged apis from spec - serverApis, taggedApis, apiCollections, headers, verifications := getServiceApis(spec, spectypes.APIInterfaceJsonRPC) - apip.BaseChainParser.Construct(spec, taggedApis, serverApis, apiCollections, headers, verifications, apip.BaseChainParser.extensionParser) + internalPaths, serverApis, taggedApis, apiCollections, headers, verifications := getServiceApis(spec, spectypes.APIInterfaceJsonRPC) + apip.BaseChainParser.Construct(spec, internalPaths, taggedApis, serverApis, apiCollections, headers, verifications, apip.BaseChainParser.extensionParser) } func (apip *JsonRPCChainParser) GetInternalPaths() map[string]struct{} { @@ -444,15 +449,17 @@ func (apil *JsonRPCChainListener) Serve(ctx context.Context, cmdFlags common.Con logFormattedMsg = utils.FormatLongString(logFormattedMsg, relayMsgLogMaxChars) } + path := "/" + fiberCtx.Params("*") utils.LavaFormatDebug("in <<<", utils.LogAttr("GUID", ctx), + utils.LogAttr("path", path), utils.LogAttr("seed", msgSeed), utils.LogAttr("_msg", logFormattedMsg), utils.LogAttr("dappID", dappID), utils.LogAttr("headers", headers), ) refererMatch := fiberCtx.Params(refererMatchString, "") - relayResult, err := apil.relaySender.SendRelay(ctx, "", msg, http.MethodPost, dappID, consumerIp, metricsData, headers) + relayResult, err := apil.relaySender.SendRelay(ctx, path, msg, http.MethodPost, dappID, consumerIp, metricsData, headers) if refererMatch != "" && apil.refererData != nil && err == nil { go apil.refererData.SendReferer(refererMatch, chainID, msg, metadataValues, nil) } @@ -586,7 +593,7 @@ func (cp *JrpcChainProxy) start(ctx context.Context, nConns uint, nodeUrl common return nil } -func (cp *JrpcChainProxy) sendBatchMessage(ctx context.Context, nodeMessage *rpcInterfaceMessages.JsonrpcBatchMessage, chainMessage ChainMessageForSend) (relayReply *pairingtypes.RelayReply, err error) { +func (cp *JrpcChainProxy) sendBatchMessage(ctx context.Context, nodeMessage *rpcInterfaceMessages.JsonrpcBatchMessage, chainMessage ChainMessageForSend) (relayReply *RelayReplyWrapper, err error) { internalPath := chainMessage.GetApiCollection().CollectionData.InternalPath rpc, err := cp.conn[internalPath].GetRpc(ctx, true) if err != nil { @@ -627,13 +634,17 @@ func (cp *JrpcChainProxy) sendBatchMessage(ctx context.Context, nodeMessage *rpc if err != nil { return nil, err } - reply := &pairingtypes.RelayReply{ - Data: retData, + reply := &RelayReplyWrapper{ + StatusCode: http.StatusOK, // status code is used only for rest at the moment + + RelayReply: &pairingtypes.RelayReply{ + Data: retData, + }, } return reply, nil } -func (cp *JrpcChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *pairingtypes.RelayReply, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { +func (cp *JrpcChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *RelayReplyWrapper, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { // Get node rpcInputMessage := chainMessage.GetRPCMessage() @@ -725,8 +736,12 @@ func (cp *JrpcChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, return nil, "", nil, err } - reply := &pairingtypes.RelayReply{ - Data: retData, + reply := &RelayReplyWrapper{ + StatusCode: http.StatusOK, // status code is used only for rest at the moment + + RelayReply: &pairingtypes.RelayReply{ + Data: retData, + }, } if ch != nil { diff --git a/protocol/chainlib/jsonRPC_test.go b/protocol/chainlib/jsonRPC_test.go index 216f35db0c..850aa78b08 100644 --- a/protocol/chainlib/jsonRPC_test.go +++ b/protocol/chainlib/jsonRPC_test.go @@ -66,7 +66,7 @@ func TestJSONChainParser_NilGuard(t *testing.T) { apip.SetSpec(spectypes.Spec{}) apip.DataReliabilityParams() apip.ChainBlockStats() - apip.getSupportedApi("", "") + apip.getSupportedApi("", "", "") apip.ParseMsg("", []byte{}, "", nil, extensionslib.ExtensionInfo{LatestBlock: 0}) } @@ -77,7 +77,7 @@ func TestJSONGetSupportedApi(t *testing.T) { serverApis: map[ApiKey]ApiContainer{{Name: "API1", ConnectionType: connectionType_test}: {api: &spectypes.Api{Name: "API1", Enabled: true}, collectionKey: CollectionKey{ConnectionType: connectionType_test}}}, }, } - api, err := apip.getSupportedApi("API1", connectionType_test) + api, err := apip.getSupportedApi("API1", connectionType_test, "") assert.NoError(t, err) assert.Equal(t, "API1", api.api.Name) @@ -87,7 +87,7 @@ func TestJSONGetSupportedApi(t *testing.T) { serverApis: map[ApiKey]ApiContainer{{Name: "API1", ConnectionType: connectionType_test}: {api: &spectypes.Api{Name: "API1", Enabled: true}, collectionKey: CollectionKey{ConnectionType: connectionType_test}}}, }, } - _, err = apip.getSupportedApi("API2", connectionType_test) + _, err = apip.getSupportedApi("API2", connectionType_test, "") assert.Error(t, err) // Test case 3: Returns error if the API is disabled @@ -96,7 +96,7 @@ func TestJSONGetSupportedApi(t *testing.T) { serverApis: map[ApiKey]ApiContainer{{Name: "API1", ConnectionType: connectionType_test}: {api: &spectypes.Api{Name: "API1", Enabled: false}, collectionKey: CollectionKey{ConnectionType: connectionType_test}}}, }, } - _, err = apip.getSupportedApi("API1", connectionType_test) + _, err = apip.getSupportedApi("API1", connectionType_test, "") assert.Error(t, err) } @@ -180,7 +180,7 @@ func TestAddonAndVerifications(t *testing.T) { require.NoError(t, err) reply, _, _, _, _, err := chainRouter.SendNodeMsg(ctx, nil, chainMessage, []string{verification.Extension}) require.NoError(t, err) - _, err = FormatResponseForParsing(reply, chainMessage) + _, err = FormatResponseForParsing(reply.RelayReply, chainMessage) require.NoError(t, err) } if closeServer != nil { @@ -293,7 +293,7 @@ func TestJsonRpcBatchCall(t *testing.T) { require.True(t, gotCalled) require.NoError(t, err) require.NotNil(t, relayReply) - require.Equal(t, response, string(relayReply.Data)) + require.Equal(t, response, string(relayReply.RelayReply.Data)) defer func() { if closeServer != nil { closeServer() @@ -334,10 +334,50 @@ func TestJsonRpcBatchCallSameID(t *testing.T) { require.True(t, gotCalled) require.NoError(t, err) require.NotNil(t, relayReply) - require.Equal(t, responseExpected, string(relayReply.Data)) + require.Equal(t, responseExpected, string(relayReply.RelayReply.Data)) defer func() { if closeServer != nil { closeServer() } }() } + +func TestJsonRpcInternalPathsMultipleVersions(t *testing.T) { + ctx := context.Background() + serverHandle := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Handle the incoming request and provide the desired response + w.WriteHeader(http.StatusOK) + fmt.Fprintf(w, `{"jsonrpc":"2.0","id":1,"result":"%s"}`, r.RequestURI) + }) + chainParser, chainProxy, chainFetcher, closeServer, _, err := CreateChainLibMocks(ctx, "STRK", spectypes.APIInterfaceJsonRPC, serverHandle, "../../", nil) + require.NoError(t, err) + require.NotNil(t, chainParser) + require.NotNil(t, chainProxy) + require.NotNil(t, chainFetcher) + v5_path := "/rpc/v0_5" + v6_path := "/rpc/v0_6" + req_data := []byte(`{"jsonrpc": "2.0", "id": 1, "method": "starknet_specVersion", "params": []}`) + chainMessage, err := chainParser.ParseMsg("", req_data, http.MethodPost, nil, extensionslib.ExtensionInfo{LatestBlock: 0}) + require.NoError(t, err) + api := chainMessage.GetApi() + collection := chainMessage.GetApiCollection() + require.Equal(t, "starknet_specVersion", api.Name) + require.Equal(t, "", collection.CollectionData.InternalPath) + + chainMessage, err = chainParser.ParseMsg(v5_path, req_data, http.MethodPost, nil, extensionslib.ExtensionInfo{LatestBlock: 0}) + require.NoError(t, err) + api = chainMessage.GetApi() + collection = chainMessage.GetApiCollection() + require.Equal(t, "starknet_specVersion", api.Name) + require.Equal(t, v5_path, collection.CollectionData.InternalPath) + + chainMessage, err = chainParser.ParseMsg(v6_path, req_data, http.MethodPost, nil, extensionslib.ExtensionInfo{LatestBlock: 0}) + require.NoError(t, err) + api = chainMessage.GetApi() + collection = chainMessage.GetApiCollection() + require.Equal(t, "starknet_specVersion", api.Name) + require.Equal(t, v6_path, collection.CollectionData.InternalPath) + if closeServer != nil { + closeServer() + } +} diff --git a/protocol/chainlib/rest.go b/protocol/chainlib/rest.go index 365ea0b289..739fab9f96 100644 --- a/protocol/chainlib/rest.go +++ b/protocol/chainlib/rest.go @@ -200,8 +200,8 @@ func (apip *RestChainParser) SetSpec(spec spectypes.Spec) { defer apip.rwLock.Unlock() // extract server and tagged apis from spec - serverApis, taggedApis, apiCollections, headers, verifications := getServiceApis(spec, spectypes.APIInterfaceRest) - apip.BaseChainParser.Construct(spec, taggedApis, serverApis, apiCollections, headers, verifications, apip.BaseChainParser.extensionParser) + internalPaths, serverApis, taggedApis, apiCollections, headers, verifications := getServiceApis(spec, spectypes.APIInterfaceRest) + apip.BaseChainParser.Construct(spec, internalPaths, taggedApis, serverApis, apiCollections, headers, verifications, apip.BaseChainParser.extensionParser) } // DataReliabilityParams returns data reliability params from spec (spec.enabled and spec.dataReliabilityThreshold) @@ -454,7 +454,7 @@ func NewRestChainProxy(ctx context.Context, nConns uint, rpcProviderEndpoint lav return rcp, nil } -func (rcp *RestChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *pairingtypes.RelayReply, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { +func (rcp *RestChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *RelayReplyWrapper, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { if ch != nil { return nil, "", nil, utils.LavaFormatError("Subscribe is not allowed on rest", nil) } @@ -537,15 +537,18 @@ func (rcp *RestChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, return nil, "", nil, err } - reply := &pairingtypes.RelayReply{ - Data: body, - Metadata: convertToMetadataMapOfSlices(res.Header), + reply := &RelayReplyWrapper{ + StatusCode: res.StatusCode, + RelayReply: &pairingtypes.RelayReply{ + Data: body, + Metadata: convertToMetadataMapOfSlices(res.Header), + }, } // checking if rest reply data is in json format - err = rcp.HandleJSONFormatError(reply.Data) + err = rcp.HandleJSONFormatError(reply.RelayReply.Data) if err != nil { - return nil, "", nil, utils.LavaFormatError("Rest reply is neither a JSON object nor a JSON array of objects", nil, utils.Attribute{Key: "reply.Data", Value: string(reply.Data)}) + return nil, "", nil, utils.LavaFormatError("Rest reply is neither a JSON object nor a JSON array of objects", nil, utils.Attribute{Key: "reply.Data", Value: string(reply.RelayReply.Data)}) } return reply, "", nil, nil diff --git a/protocol/chainlib/rest_test.go b/protocol/chainlib/rest_test.go index 73bac82797..e3d435af70 100644 --- a/protocol/chainlib/rest_test.go +++ b/protocol/chainlib/rest_test.go @@ -212,7 +212,7 @@ func TestParsingRequestedBlocksHeadersRest(t *testing.T) { require.Equal(t, test.requestedBlock, latestReqBlock) reply, _, _, _, _, err := chainRouter.SendNodeMsg(ctx, nil, chainMessage, nil) require.NoError(t, err) - parserInput, err := FormatResponseForParsing(reply, chainMessage) + parserInput, err := FormatResponseForParsing(reply.RelayReply, chainMessage) require.NoError(t, err) blockNum, err := parser.ParseBlockFromReply(parserInput, parsingForCrafting.ResultParsing) require.NoError(t, err) @@ -286,7 +286,7 @@ func TestSettingRequestedBlocksHeadersRest(t *testing.T) { require.Equal(t, test.block, latestReqBlock) // expected behavior is that it doesn't change the original requested block reply, _, _, _, _, err := chainRouter.SendNodeMsg(ctx, nil, chainMessage, nil) require.NoError(t, err) - parserInput, err := FormatResponseForParsing(reply, chainMessage) + parserInput, err := FormatResponseForParsing(reply.RelayReply, chainMessage) require.NoError(t, err) blockNum, err := parser.ParseBlockFromReply(parserInput, parsingForCrafting.ResultParsing) require.NoError(t, err) diff --git a/protocol/chainlib/tendermintRPC.go b/protocol/chainlib/tendermintRPC.go index 9cfa8fbdfd..6e3de70824 100644 --- a/protocol/chainlib/tendermintRPC.go +++ b/protocol/chainlib/tendermintRPC.go @@ -54,7 +54,8 @@ func (apip *TendermintChainParser) getSupportedApi(name, connectionType string) if apip == nil { return nil, errors.New("ChainParser not defined") } - return apip.BaseChainParser.getSupportedApi(name, connectionType) + apiKey := ApiKey{Name: name, ConnectionType: connectionType} + return apip.BaseChainParser.getSupportedApi(apiKey) } func (apip *TendermintChainParser) CraftMessage(parsing *spectypes.ParseDirective, connectionType string, craftData *CraftData, metadata []pairingtypes.Metadata) (ChainMessageForSend, error) { @@ -270,8 +271,8 @@ func (apip *TendermintChainParser) SetSpec(spec spectypes.Spec) { defer apip.rwLock.Unlock() // extract server and tagged apis from spec - serverApis, taggedApis, apiCollections, headers, verifications := getServiceApis(spec, spectypes.APIInterfaceTendermintRPC) - apip.BaseChainParser.Construct(spec, taggedApis, serverApis, apiCollections, headers, verifications, apip.BaseChainParser.extensionParser) + internalPaths, serverApis, taggedApis, apiCollections, headers, verifications := getServiceApis(spec, spectypes.APIInterfaceTendermintRPC) + apip.BaseChainParser.Construct(spec, internalPaths, taggedApis, serverApis, apiCollections, headers, verifications, apip.BaseChainParser.extensionParser) } // DataReliabilityParams returns data reliability params from spec (spec.enabled and spec.dataReliabilityThreshold) @@ -640,7 +641,7 @@ func (cp *tendermintRpcChainProxy) addHttpConnector(ctx context.Context, nConns return nil } -func (cp *tendermintRpcChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *pairingtypes.RelayReply, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { +func (cp *tendermintRpcChainProxy) SendNodeMsg(ctx context.Context, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *RelayReplyWrapper, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { rpcInputMessage := chainMessage.GetRPCMessage() nodeMessage, ok := rpcInputMessage.(*rpcInterfaceMessages.TendermintrpcMessage) if !ok { @@ -662,7 +663,7 @@ func (cp *tendermintRpcChainProxy) SendNodeMsg(ctx context.Context, ch chan inte return cp.SendRPC(ctx, nodeMessage, ch, chainMessage) } -func (cp *tendermintRpcChainProxy) SendURI(ctx context.Context, nodeMessage *rpcInterfaceMessages.TendermintrpcMessage, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *pairingtypes.RelayReply, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { +func (cp *tendermintRpcChainProxy) SendURI(ctx context.Context, nodeMessage *rpcInterfaceMessages.TendermintrpcMessage, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *RelayReplyWrapper, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { // check if the input channel is not nil if ch != nil { // return an error if the channel is not nil @@ -730,21 +731,24 @@ func (cp *tendermintRpcChainProxy) SendURI(ctx context.Context, nodeMessage *rpc } // create a new relay reply struct with the response body as the data - reply := &pairingtypes.RelayReply{ - Data: body, + reply := &RelayReplyWrapper{ + StatusCode: http.StatusOK, // status code is used only for rest at the moment + RelayReply: &pairingtypes.RelayReply{ + Data: body, + }, } // checking if rest reply data is in json format - err = cp.HandleJSONFormatError(reply.Data) + err = cp.HandleJSONFormatError(reply.RelayReply.Data) if err != nil { - return nil, "", nil, utils.LavaFormatError("Tendermint reply is neither a JSON object nor a JSON array of objects", nil, utils.Attribute{Key: "reply.Data", Value: string(reply.Data)}) + return nil, "", nil, utils.LavaFormatError("Tendermint reply is neither a JSON object nor a JSON array of objects", nil, utils.Attribute{Key: "reply.Data", Value: string(reply.RelayReply.Data)}) } return reply, "", nil, nil } // SendRPC sends Tendermint HTTP or WebSockets call -func (cp *tendermintRpcChainProxy) SendRPC(ctx context.Context, nodeMessage *rpcInterfaceMessages.TendermintrpcMessage, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *pairingtypes.RelayReply, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { +func (cp *tendermintRpcChainProxy) SendRPC(ctx context.Context, nodeMessage *rpcInterfaceMessages.TendermintrpcMessage, ch chan interface{}, chainMessage ChainMessageForSend) (relayReply *RelayReplyWrapper, subscriptionID string, relayReplyServer *rpcclient.ClientSubscription, err error) { // Get rpc connection from the connection pool var rpc *rpcclient.Client if ch != nil { @@ -836,8 +840,11 @@ func (cp *tendermintRpcChainProxy) SendRPC(ctx context.Context, nodeMessage *rpc } // create a new relay reply struct - reply := &pairingtypes.RelayReply{ - Data: data, + reply := &RelayReplyWrapper{ + StatusCode: http.StatusOK, // status code is used only for rest at the moment + RelayReply: &pairingtypes.RelayReply{ + Data: data, + }, } if ch != nil { diff --git a/protocol/chainlib/tendermintRPC_test.go b/protocol/chainlib/tendermintRPC_test.go index a48752b4bc..aaa24f0847 100644 --- a/protocol/chainlib/tendermintRPC_test.go +++ b/protocol/chainlib/tendermintRPC_test.go @@ -195,7 +195,7 @@ func TestTendermintRpcBatchCall(t *testing.T) { require.True(t, gotCalled) require.NoError(t, err) require.NotNil(t, relayReply) - require.Equal(t, response, string(relayReply.Data)) + require.Equal(t, response, string(relayReply.RelayReply.Data)) defer func() { if closeServer != nil { closeServer() @@ -237,7 +237,7 @@ func TestTendermintRpcBatchCallWithSameID(t *testing.T) { require.True(t, gotCalled) require.NoError(t, err) require.NotNil(t, relayReply) - require.Equal(t, response, string(relayReply.Data)) + require.Equal(t, response, string(relayReply.RelayReply.Data)) defer func() { if closeServer != nil { closeServer() diff --git a/protocol/metrics/analytics.go b/protocol/metrics/analytics.go index f712807890..11048fc135 100644 --- a/protocol/metrics/analytics.go +++ b/protocol/metrics/analytics.go @@ -22,6 +22,7 @@ type RelayMetrics struct { ComputeUnits uint64 Source RelaySource Origin string + ApiMethod string } type RelayAnalyticsDTO struct { diff --git a/protocol/metrics/metrics_consumer_manager.go b/protocol/metrics/metrics_consumer_manager.go index 3252dcdc9a..86195ca878 100644 --- a/protocol/metrics/metrics_consumer_manager.go +++ b/protocol/metrics/metrics_consumer_manager.go @@ -28,15 +28,22 @@ type ConsumerMetricsManager struct { LatestBlockMetric *prometheus.GaugeVec LatestProviderRelay *prometheus.GaugeVec virtualEpochMetric *prometheus.GaugeVec + apiMethodCalls *prometheus.GaugeVec endpointsHealthChecksOkMetric prometheus.Gauge endpointsHealthChecksOk uint64 lock sync.Mutex protocolVersionMetric *prometheus.GaugeVec providerRelays map[string]uint64 + addMethodsApiGauge bool } -func NewConsumerMetricsManager(networkAddress string) *ConsumerMetricsManager { - if networkAddress == DisabledFlagOption { +type ConsumerMetricsManagerOptions struct { + NetworkAddress string + AddMethodsApiGauge bool +} + +func NewConsumerMetricsManager(options ConsumerMetricsManagerOptions) *ConsumerMetricsManager { + if options.NetworkAddress == DisabledFlagOption { utils.LavaFormatWarning("prometheus endpoint inactive, option is disabled", nil) return nil } @@ -114,6 +121,11 @@ func NewConsumerMetricsManager(networkAddress string) *ConsumerMetricsManager { Name: "lava_consumer_overall_health", Help: "At least one endpoint is healthy", }) + apiSpecificsMetric := prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Name: "lava_consumer_api_specifics", + Help: "api usage specifics", + }, []string{"spec", "apiInterface", "method"}) + endpointsHealthChecksOkMetric.Set(1) protocolVersionMetric := prometheus.NewGaugeVec(prometheus.GaugeOpts{ Name: "lava_provider_protocol_version", @@ -138,6 +150,7 @@ func NewConsumerMetricsManager(networkAddress string) *ConsumerMetricsManager { prometheus.MustRegister(totalRelaysSentByNewBatchTickerMetric) prometheus.MustRegister(currentNumberOfOpenSessionsMetric) prometheus.MustRegister(currentNumberOfBlockedSessionsMetric) + prometheus.MustRegister(apiSpecificsMetric) consumerMetricsManager := &ConsumerMetricsManager{ totalCURequestedMetric: totalCURequestedMetric, @@ -159,6 +172,8 @@ func NewConsumerMetricsManager(networkAddress string) *ConsumerMetricsManager { totalRelaysSentByNewBatchTickerMetric: totalRelaysSentByNewBatchTickerMetric, currentNumberOfOpenSessionsMetric: currentNumberOfOpenSessionsMetric, currentNumberOfBlockedSessionsMetric: currentNumberOfBlockedSessionsMetric, + apiMethodCalls: apiSpecificsMetric, + addMethodsApiGauge: options.AddMethodsApiGauge, } http.Handle("/metrics", promhttp.Handler()) @@ -180,8 +195,8 @@ func NewConsumerMetricsManager(networkAddress string) *ConsumerMetricsManager { http.HandleFunc("/metrics/health-overall", overallHealthHandler) // Old go func() { - utils.LavaFormatInfo("prometheus endpoint listening", utils.Attribute{Key: "Listen Address", Value: networkAddress}) - http.ListenAndServe(networkAddress, nil) + utils.LavaFormatInfo("prometheus endpoint listening", utils.Attribute{Key: "Listen Address", Value: options.NetworkAddress}) + http.ListenAndServe(options.NetworkAddress, nil) }() return consumerMetricsManager @@ -202,6 +217,9 @@ func (pme *ConsumerMetricsManager) SetRelayMetrics(relayMetric *RelayMetrics, er pme.latencyMetric.WithLabelValues(relayMetric.ChainID, relayMetric.APIType).Set(float64(relayMetric.Latency)) pme.totalCURequestedMetric.WithLabelValues(relayMetric.ChainID, relayMetric.APIType).Add(float64(relayMetric.ComputeUnits)) pme.totalRelaysRequestedMetric.WithLabelValues(relayMetric.ChainID, relayMetric.APIType).Add(1) + if pme.addMethodsApiGauge && relayMetric.ApiMethod != "" { // pme.addMethodsApiGauge never changes so its safe to read concurrently + pme.apiMethodCalls.WithLabelValues(relayMetric.ChainID, relayMetric.APIType, relayMetric.ApiMethod).Add(1) + } if !relayMetric.Success { pme.totalErroredMetric.WithLabelValues(relayMetric.ChainID, relayMetric.APIType).Add(1) } diff --git a/protocol/metrics/metrics_provider_manager.go b/protocol/metrics/metrics_provider_manager.go index 71beeda391..721a2faa49 100644 --- a/protocol/metrics/metrics_provider_manager.go +++ b/protocol/metrics/metrics_provider_manager.go @@ -14,9 +14,10 @@ import ( ) const ( - MetricsListenFlagName = "metrics-listen-address" - RelayServerFlagName = "relay-server-address" - DisabledFlagOption = "disabled" + MetricsListenFlagName = "metrics-listen-address" + AddApiMethodCallsMetrics = "add-api-method-metrics" + RelayServerFlagName = "relay-server-address" + DisabledFlagOption = "disabled" ) type ProviderMetricsManager struct { diff --git a/protocol/rpcconsumer/rpcconsumer.go b/protocol/rpcconsumer/rpcconsumer.go index 16919f227f..eae911bcb2 100644 --- a/protocol/rpcconsumer/rpcconsumer.go +++ b/protocol/rpcconsumer/rpcconsumer.go @@ -98,9 +98,10 @@ type ConsumerStateTrackerInf interface { } type AnalyticsServerAddressess struct { - MetricsListenAddress string - RelayServerAddress string - ReportsAddressFlag string + AddApiMethodCallsMetrics bool + MetricsListenAddress string + RelayServerAddress string + ReportsAddressFlag string } type RPCConsumer struct { consumerStateTracker ConsumerStateTrackerInf @@ -127,8 +128,8 @@ func (rpcc *RPCConsumer) Start(ctx context.Context, options *rpcConsumerStartOpt } options.refererData.ReferrerClient = metrics.NewConsumerReferrerClient(options.refererData.Address) consumerReportsManager := metrics.NewConsumerReportsClient(options.analyticsServerAddressess.ReportsAddressFlag) - consumerMetricsManager := metrics.NewConsumerMetricsManager(options.analyticsServerAddressess.MetricsListenAddress) // start up prometheus metrics - consumerUsageserveManager := metrics.NewConsumerRelayServerClient(options.analyticsServerAddressess.RelayServerAddress) // start up relay server reporting + consumerMetricsManager := metrics.NewConsumerMetricsManager(metrics.ConsumerMetricsManagerOptions{NetworkAddress: options.analyticsServerAddressess.MetricsListenAddress, AddMethodsApiGauge: options.analyticsServerAddressess.AddApiMethodCallsMetrics}) // start up prometheus metrics + consumerUsageserveManager := metrics.NewConsumerRelayServerClient(options.analyticsServerAddressess.RelayServerAddress) // start up relay server reporting rpcConsumerMetrics, err := metrics.NewRPCConsumerLogs(consumerMetricsManager, consumerUsageserveManager) if err != nil { utils.LavaFormatFatal("failed creating RPCConsumer logs", err) @@ -502,9 +503,10 @@ rpcconsumer consumer_examples/full_consumer_example.yml --cache-be "127.0.0.1:77 } analyticsServerAddressess := AnalyticsServerAddressess{ - MetricsListenAddress: viper.GetString(metrics.MetricsListenFlagName), - RelayServerAddress: viper.GetString(metrics.RelayServerFlagName), - ReportsAddressFlag: viper.GetString(reportsSendBEAddress), + AddApiMethodCallsMetrics: viper.GetBool(metrics.AddApiMethodCallsMetrics), + MetricsListenAddress: viper.GetString(metrics.MetricsListenFlagName), + RelayServerAddress: viper.GetString(metrics.RelayServerFlagName), + ReportsAddressFlag: viper.GetString(reportsSendBEAddress), } var refererData *chainlib.RefererData @@ -548,6 +550,7 @@ rpcconsumer consumer_examples/full_consumer_example.yml --cache-be "127.0.0.1:77 cmdRPCConsumer.Flags().String(performance.CacheFlagName, "", "address for a cache server to improve performance") cmdRPCConsumer.Flags().Var(&strategyFlag, "strategy", fmt.Sprintf("the strategy to use to pick providers (%s)", strings.Join(strategyNames, "|"))) cmdRPCConsumer.Flags().String(metrics.MetricsListenFlagName, metrics.DisabledFlagOption, "the address to expose prometheus metrics (such as localhost:7779)") + cmdRPCConsumer.Flags().Bool(metrics.AddApiMethodCallsMetrics, false, "adding a counter gauge for each method called per chain per api interface") cmdRPCConsumer.Flags().String(metrics.RelayServerFlagName, metrics.DisabledFlagOption, "the http address of the relay usage server api endpoint (example http://127.0.0.1:8080)") cmdRPCConsumer.Flags().Bool(DebugRelaysFlagName, false, "adding debug information to relays") // CORS related flags diff --git a/protocol/rpcconsumer/rpcconsumer_server.go b/protocol/rpcconsumer/rpcconsumer_server.go index 412fc916e7..df14ff6a58 100644 --- a/protocol/rpcconsumer/rpcconsumer_server.go +++ b/protocol/rpcconsumer/rpcconsumer_server.go @@ -321,7 +321,9 @@ func (rpccs *RPCConsumerServer) SendRelay( if analytics != nil { currentLatency := time.Since(relaySentTime) analytics.Latency = currentLatency.Milliseconds() - analytics.ComputeUnits = chainMessage.GetApi().ComputeUnits + api := chainMessage.GetApi() + analytics.ComputeUnits = api.ComputeUnits + analytics.ApiMethod = api.Name } rpccs.relaysMonitor.LogRelay() return returnedResult, nil @@ -683,7 +685,7 @@ func (rpccs *RPCConsumerServer) sendRelayToProvider( copyReply := &pairingtypes.RelayReply{} copyReplyErr := protocopy.DeepCopyProtoObject(localRelayResult.Reply, copyReply) // set cache in a non blocking call - + statusCode := localRelayResult.StatusCode requestedBlock := localRelayResult.Request.RelayData.RequestBlock // get requested block before removing it from the data seenBlock := localRelayResult.Request.RelayData.SeenBlock // get seen block before removing it from the data hashKey, _, hashErr := chainlib.HashCacheRequest(localRelayResult.Request.RelayData, chainId) // get the hash (this changes the data) @@ -706,6 +708,9 @@ func (rpccs *RPCConsumerServer) sendRelayToProvider( new_ctx, cancel := context.WithTimeout(new_ctx, common.DataReliabilityTimeoutIncrease) defer cancel() _, averageBlockTime, _, _ := rpccs.chainParser.ChainBlockStats() + // we don't want to cache node errors for too long. what can happen is a finalized block gets an error + // and we cache it for a long period of time. + isNodeError, _ := chainMessage.CheckResponseError(copyReply.Data, statusCode) err2 := rpccs.cache.SetEntry(new_ctx, &pairingtypes.RelayCacheSet{ RequestHash: hashKey, @@ -718,6 +723,7 @@ func (rpccs *RPCConsumerServer) sendRelayToProvider( OptionalMetadata: nil, SharedStateId: sharedStateId, AverageBlockTime: int64(averageBlockTime), // by using average block time we can set longer TTL + IsNodeError: isNodeError, }) if err2 != nil { utils.LavaFormatWarning("error updating cache with new entry", err2) @@ -761,7 +767,7 @@ func (rpccs *RPCConsumerServer) relayInner(ctx context.Context, singleConsumerSe } if rpccs.debugRelays { - utils.LavaFormatDebug("sending relay to provider", + attributes := []utils.Attribute{ utils.LogAttr("GUID", ctx), utils.LogAttr("addon", relayRequest.RelayData.Addon), utils.LogAttr("extensions", relayRequest.RelayData.Extensions), @@ -776,7 +782,14 @@ func (rpccs *RPCConsumerServer) relayInner(ctx context.Context, singleConsumerSe utils.LogAttr("latency", relayLatency), utils.LogAttr("replyErred", err != nil), utils.LogAttr("replyLatestBlock", reply.GetLatestBlock()), - ) + utils.LogAttr("method", chainMessage.GetApi().Name), + } + internalPath := chainMessage.GetApiCollection().CollectionData.InternalPath + if internalPath != "" { + attributes = append(attributes, utils.LogAttr("internal_path", internalPath), + utils.LogAttr("apiUrl", relayRequest.RelayData.ApiUrl)) + } + utils.LavaFormatDebug("sending relay to provider", attributes...) } if err != nil { diff --git a/protocol/rpcprovider/reliabilitymanager/reliability_manager.go b/protocol/rpcprovider/reliabilitymanager/reliability_manager.go index 48e302cfde..9ecad9fbde 100644 --- a/protocol/rpcprovider/reliabilitymanager/reliability_manager.go +++ b/protocol/rpcprovider/reliabilitymanager/reliability_manager.go @@ -111,11 +111,15 @@ func (rm *ReliabilityManager) VoteHandler(voteParams *VoteParams, nodeHeight uin utils.Attribute{Key: "voteID", Value: voteID}, utils.Attribute{Key: "chainID", Value: voteParams.ChainID}) } // TODO: get extensions and addons from the request - reply, _, _, _, _, err := rm.chainRouter.SendNodeMsg(ctx, nil, chainMessage, nil) + replyWrapper, _, _, _, _, err := rm.chainRouter.SendNodeMsg(ctx, nil, chainMessage, nil) if err != nil { return utils.LavaFormatError("vote relay send has failed", err, utils.Attribute{Key: "ApiURL", Value: voteParams.ApiURL}, utils.Attribute{Key: "RequestData", Value: voteParams.RequestData}) } + if replyWrapper == nil || replyWrapper.RelayReply == nil { + return utils.LavaFormatError("vote relay send has failed, relayWrapper is nil", nil, utils.Attribute{Key: "ApiURL", Value: voteParams.ApiURL}, utils.Attribute{Key: "RequestData", Value: voteParams.RequestData}) + } + reply := replyWrapper.RelayReply reply.Metadata, _, _ = rm.chainParser.HandleHeaders(reply.Metadata, chainMessage.GetApiCollection(), spectypes.Header_pass_reply) nonce := rand.Int63() relayData := BuildRelayDataFromVoteParams(voteParams) diff --git a/protocol/rpcprovider/rpcprovider_server.go b/protocol/rpcprovider/rpcprovider_server.go index d77f32d4a4..d43cc58b2f 100644 --- a/protocol/rpcprovider/rpcprovider_server.go +++ b/protocol/rpcprovider/rpcprovider_server.go @@ -378,10 +378,14 @@ func (rpcps *RPCProviderServer) TryRelaySubscribe(ctx context.Context, requestBl var clientSub *rpcclient.ClientSubscription var subscriptionID string subscribeRepliesChan := make(chan interface{}) - reply, subscriptionID, clientSub, _, _, err := rpcps.chainRouter.SendNodeMsg(ctx, subscribeRepliesChan, chainMessage, nil) + replyWrapper, subscriptionID, clientSub, _, _, err := rpcps.chainRouter.SendNodeMsg(ctx, subscribeRepliesChan, chainMessage, nil) if err != nil { return false, utils.LavaFormatError("Subscription failed", err, utils.Attribute{Key: "GUID", Value: ctx}) } + if replyWrapper == nil || replyWrapper.RelayReply == nil { + return false, utils.LavaFormatError("Subscription failed, relayWrapper or RelayReply are nil", nil, utils.Attribute{Key: "GUID", Value: ctx}) + } + reply = replyWrapper.RelayReply reply.Metadata, _, _ = rpcps.chainParser.HandleHeaders(reply.Metadata, chainMessage.GetApiCollection(), spectypes.Header_pass_reply) if clientSub == nil { // failed subscription, but not an error. (probably a node error) @@ -755,11 +759,16 @@ func (rpcps *RPCProviderServer) TryRelay(ctx context.Context, request *pairingty if debugConsistency { utils.LavaFormatDebug("adding stickiness header", utils.LogAttr("tokenFromContext", common.GetTokenFromGrpcContext(ctx)), utils.LogAttr("unique_token", common.GetUniqueToken(consumerAddr.String(), common.GetIpFromGrpcContext(ctx)))) } - - reply, _, _, _, _, err = rpcps.chainRouter.SendNodeMsg(ctx, nil, chainMsg, request.RelayData.Extensions) + var replyWrapper *chainlib.RelayReplyWrapper + replyWrapper, _, _, _, _, err = rpcps.chainRouter.SendNodeMsg(ctx, nil, chainMsg, request.RelayData.Extensions) if err != nil { return nil, utils.LavaFormatError("Sending chainMsg failed", err, utils.Attribute{Key: "GUID", Value: ctx}, utils.Attribute{Key: "specID", Value: rpcps.rpcProviderEndpoint.ChainID}) } + if replyWrapper == nil || replyWrapper.RelayReply == nil { + return nil, utils.LavaFormatError("Relay Wrapper returned nil without an error", nil, utils.Attribute{Key: "GUID", Value: ctx}, utils.Attribute{Key: "specID", Value: rpcps.rpcProviderEndpoint.ChainID}) + } + + reply = replyWrapper.RelayReply if debugLatency { utils.LavaFormatDebug("node reply received", utils.Attribute{Key: "timeTaken", Value: time.Since(sendTime)}, utils.Attribute{Key: "GUID", Value: ctx}, utils.Attribute{Key: "specID", Value: rpcps.rpcProviderEndpoint.ChainID}) } @@ -771,6 +780,9 @@ func (rpcps *RPCProviderServer) TryRelay(ctx context.Context, request *pairingty hashKey, _, hashErr := chainlib.HashCacheRequest(request.RelayData, rpcps.rpcProviderEndpoint.ChainID) // get the hash (this changes the data) copyReply := &pairingtypes.RelayReply{} copyReplyErr := protocopy.DeepCopyProtoObject(reply, copyReply) + + // get status code to decide if its a node error + statusCode := replyWrapper.StatusCode go func() { if hashErr != nil || copyReplyErr != nil { utils.LavaFormatError("Failed copying relay private data on TryRelay", nil, utils.LogAttr("copyReplyErr", copyReplyErr), utils.LogAttr("hashErr", hashErr)) @@ -783,6 +795,10 @@ func (rpcps *RPCProviderServer) TryRelay(ctx context.Context, request *pairingty utils.LavaFormatError("TryRelay failed calculating hash for cach.SetEntry", err) return } + // in case the error is a node error we don't want to cache the response for a long period of time + // so users wont get errors if the error was temporary + isNodeError, _ := chainMsg.CheckResponseError(copyReply.Data, statusCode) + err = cache.SetEntry(new_ctx, &pairingtypes.RelayCacheSet{ RequestHash: hashKey, RequestedBlock: requestedBlock, @@ -793,6 +809,7 @@ func (rpcps *RPCProviderServer) TryRelay(ctx context.Context, request *pairingty OptionalMetadata: ignoredMetadata, AverageBlockTime: int64(averageBlockTime), SeenBlock: latestBlock, + IsNodeError: isNodeError, }) if err != nil && request.RelaySession.Epoch != spectypes.NOT_APPLICABLE { utils.LavaFormatWarning("error updating cache with new entry", err, utils.Attribute{Key: "GUID", Value: ctx}) diff --git a/scripts/pre_setups/init_lava_only_with_node.sh b/scripts/pre_setups/init_lava_only_with_node.sh index 883730c934..227a6298a0 100755 --- a/scripts/pre_setups/init_lava_only_with_node.sh +++ b/scripts/pre_setups/init_lava_only_with_node.sh @@ -57,7 +57,7 @@ wait_next_block screen -d -m -S consumers bash -c "source ~/.bashrc; lavap rpcconsumer \ 127.0.0.1:3360 LAV1 rest 127.0.0.1:3361 LAV1 tendermintrpc 127.0.0.1:3362 LAV1 grpc \ -$EXTRA_PORTAL_FLAGS --geolocation 1 --log_level debug --from user1 --chain-id lava --pprof-address "127.0.0.1:6060" --allow-insecure-provider-dialing --metrics-listen-address ":7779" 2>&1 | tee $LOGS_DIR/CONSUMERS.log" && sleep 0.25 +$EXTRA_PORTAL_FLAGS --geolocation 1 --log_level debug --from user1 --chain-id lava --add-api-method-metrics --allow-insecure-provider-dialing --metrics-listen-address ":7779" 2>&1 | tee $LOGS_DIR/CONSUMERS.log" && sleep 0.25 echo "--- setting up screens done ---" screen -ls \ No newline at end of file diff --git a/scripts/test_spec_full.sh b/scripts/test_spec_full.sh index 272c3f1ebf..b06291769b 100755 --- a/scripts/test_spec_full.sh +++ b/scripts/test_spec_full.sh @@ -207,7 +207,7 @@ done echo "[+]generated consumer config: $output_consumer_yaml" cat $output_consumer_yaml if [ "$dry" = false ]; then - screen -d -m -S consumers bash -c "source ~/.bashrc; lavap rpcconsumer testutil/debugging/logs/consumer.yml $EXTRA_PORTAL_FLAGS --geolocation 1 --log_level debug --from user1 --chain-id lava --allow-insecure-provider-dialing --metrics-listen-address ":7779" 2>&1 | tee $LOGS_DIR/PORTAL.log" + screen -d -m -S consumers bash -c "source ~/.bashrc; lavap rpcconsumer testutil/debugging/logs/consumer.yml $EXTRA_PORTAL_FLAGS --geolocation 1 --debug-relays --log_level debug --from user1 --chain-id lava --allow-insecure-provider-dialing --metrics-listen-address ":7779" 2>&1 | tee $LOGS_DIR/PORTAL.log" echo "[+] letting providers start and running health check then running command with flags: $test_consumer_command_args" sleep 10 diff --git a/x/dualstaking/keeper/delegate_test.go b/x/dualstaking/keeper/delegate_test.go index 37aaab59fa..7a558810be 100644 --- a/x/dualstaking/keeper/delegate_test.go +++ b/x/dualstaking/keeper/delegate_test.go @@ -536,14 +536,14 @@ func TestDualstakingUnbondStakeIsLowerThanMinStakeCausesFreeze(t *testing.T) { _, err := ts.TxDualstakingUnbond(provider1Addr, provider1Addr, ts.spec.Name, amountToUnbond) require.NoError(t, err) - stakeEntry := ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) - require.True(t, staked.IsEqual(stakeEntry.Stake)) + stakeEntry := ts.getStakeEntryCurrent(provider1Acct.Addr.String(), ts.spec.Name) + require.True(t, staked.Sub(amountToUnbond).IsEqual(stakeEntry.Stake)) // advance epoch to digest the delegate ts.AdvanceEpoch() // now in effect staked = staked.Sub(staked.Sub(minSelfDelegation.AddAmount(math.OneInt()))) - stakeEntry = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) + stakeEntry = ts.getStakeEntryCurrent(provider1Acct.Addr.String(), ts.spec.Name) require.True(t, staked.IsEqual(stakeEntry.Stake)) require.True(t, stakeEntry.IsFrozen()) } @@ -617,11 +617,11 @@ func TestDualstakingRedelegateFreezeOneUnFreezeOther(t *testing.T) { ts.AdvanceEpoch() // now in effect - stakeEntry := ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) + stakeEntry := ts.getStakeEntryCurrent(provider1Acct.Addr.String(), ts.spec.Name) require.True(t, stakeEntry.Stake.Amount.Equal(amountToUnbond.Amount)) require.True(t, stakeEntry.IsFrozen()) - stakeEntry = ts.getStakeEntry(provider2Acct.Addr.String(), ts.spec.Name) + stakeEntry = ts.getStakeEntryCurrent(provider2Acct.Addr.String(), ts.spec.Name) require.True(t, stake.IsEqual(stakeEntry.Stake)) require.True(t, stakeEntry.DelegateTotal.IsEqual(stake.SubAmount(amountToUnbond.Amount))) require.False(t, stakeEntry.IsFrozen()) @@ -634,12 +634,12 @@ func TestDualstakingRedelegateFreezeOneUnFreezeOther(t *testing.T) { ts.AdvanceEpoch() // now in effect - stakeEntry = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) + stakeEntry = ts.getStakeEntryCurrent(provider1Acct.Addr.String(), ts.spec.Name) require.True(t, stakeEntry.Stake.Amount.Equal(amountToUnbond.Amount)) require.True(t, stakeEntry.DelegateTotal.IsEqual(stake.SubAmount(amountToUnbond.Amount))) require.True(t, stakeEntry.IsFrozen()) - stakeEntry = ts.getStakeEntry(provider2Acct.Addr.String(), ts.spec.Name) + stakeEntry = ts.getStakeEntryCurrent(provider2Acct.Addr.String(), ts.spec.Name) require.True(t, stakeEntry.Stake.Amount.Equal(amountToUnbond.Amount)) require.True(t, stakeEntry.DelegateTotal.IsEqual(stake.SubAmount(amountToUnbond.Amount))) require.True(t, stakeEntry.IsFrozen()) @@ -657,7 +657,7 @@ func TestStakingUnbondStakeIsLowerThanMinStakeCausesFreeze(t *testing.T) { stakeInt := sdk.NewInt(testStake) stake := sdk.NewCoin("ulava", stakeInt) - stakeEntry := ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) + stakeEntry := ts.getStakeEntryCurrent(provider1Acct.Addr.String(), ts.spec.Name) require.True(t, stake.IsEqual(stakeEntry.Stake)) require.False(t, stakeEntry.IsFrozen()) @@ -671,7 +671,7 @@ func TestStakingUnbondStakeIsLowerThanMinStakeCausesFreeze(t *testing.T) { ts.AdvanceEpoch() // now in effect - stakeEntry = ts.getStakeEntry(provider1Acct.Addr.String(), ts.spec.Name) + stakeEntry = ts.getStakeEntryCurrent(provider1Acct.Addr.String(), ts.spec.Name) require.True(t, stakeEntry.Stake.Amount.Equal(amountToUnbond.Amount)) require.True(t, stakeEntry.IsFrozen()) } diff --git a/x/dualstaking/keeper/delegator_reward.go b/x/dualstaking/keeper/delegator_reward.go index fe0b400e32..89e0f3a975 100644 --- a/x/dualstaking/keeper/delegator_reward.go +++ b/x/dualstaking/keeper/delegator_reward.go @@ -173,15 +173,9 @@ func (k Keeper) ClaimRewards(ctx sdk.Context, delegator string, provider string) // RewardProvidersAndDelegators is the main function handling provider rewards with delegations // it returns the provider reward amount and updates the delegatorReward map with the reward portion for each delegator func (k Keeper) RewardProvidersAndDelegators(ctx sdk.Context, provider string, chainID string, totalReward sdk.Coins, senderModule string, calcOnlyProvider bool, calcOnlyDelegators bool, calcOnlyContributer bool) (providerReward sdk.Coins, claimableRewards sdk.Coins, err error) { - block := uint64(ctx.BlockHeight()) zeroCoins := sdk.NewCoins() - epoch, _, err := k.epochstorageKeeper.GetEpochStartForBlock(ctx, block) - if err != nil { - return zeroCoins, zeroCoins, utils.LavaFormatError(types.ErrCalculatingProviderReward.Error(), err, - utils.Attribute{Key: "block", Value: block}, - ) - } - stakeEntry, found := k.epochstorageKeeper.GetStakeEntryForProviderEpoch(ctx, chainID, provider, epoch) + epoch := k.epochstorageKeeper.GetCurrentNextEpoch(ctx) + stakeEntry, found := k.epochstorageKeeper.GetStakeEntryByAddressCurrent(ctx, chainID, provider) if !found { return zeroCoins, zeroCoins, err } diff --git a/x/dualstaking/keeper/helpers_test.go b/x/dualstaking/keeper/helpers_test.go index d86642d379..33ebe157b0 100644 --- a/x/dualstaking/keeper/helpers_test.go +++ b/x/dualstaking/keeper/helpers_test.go @@ -103,6 +103,18 @@ func (ts *tester) getStakeEntry(provider string, chainID string) epochstoragetyp return stakeEntry } +// getStakeEntry find the stake entry of a given provider + chainID +func (ts *tester) getStakeEntryCurrent(provider string, chainID string) epochstoragetypes.StakeEntry { + keeper := ts.Keepers.Epochstorage + + stakeEntry, found := keeper.GetStakeEntryByAddressCurrent(ts.Ctx, chainID, provider) + if !found { + panic("getStakeEntry: no stake entry: " + provider + " " + chainID) + } + + return stakeEntry +} + func (ts *tester) verifyDelegatorsBalance() { accounts := ts.AccountsMap() for key, account := range accounts { diff --git a/x/epochstorage/types/types.go b/x/epochstorage/types/types.go index b0844eb1bf..0352b70f20 100644 --- a/x/epochstorage/types/types.go +++ b/x/epochstorage/types/types.go @@ -16,6 +16,10 @@ func (stksto StakeStorage) Copy() (returnedStorage StakeStorage) { } for _, stakeEntry := range stksto.StakeEntries { + if stakeEntry.IsFrozen() { + continue + } + newStakeEntry := stakeEntry endpoints := make([]Endpoint, len(stakeEntry.Endpoints)) diff --git a/x/pairing/types/relayCache.pb.go b/x/pairing/types/relayCache.pb.go index 35665e71bf..9c5ac5d51b 100644 --- a/x/pairing/types/relayCache.pb.go +++ b/x/pairing/types/relayCache.pb.go @@ -297,6 +297,7 @@ type RelayCacheSet struct { ChainId string `protobuf:"bytes,9,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` SeenBlock int64 `protobuf:"varint,10,opt,name=seen_block,json=seenBlock,proto3" json:"seen_block,omitempty"` AverageBlockTime int64 `protobuf:"varint,11,opt,name=average_block_time,json=averageBlockTime,proto3" json:"average_block_time,omitempty"` + IsNodeError bool `protobuf:"varint,12,opt,name=is_node_error,json=isNodeError,proto3" json:"is_node_error,omitempty"` } func (m *RelayCacheSet) Reset() { *m = RelayCacheSet{} } @@ -402,6 +403,13 @@ func (m *RelayCacheSet) GetAverageBlockTime() int64 { return 0 } +func (m *RelayCacheSet) GetIsNodeError() bool { + if m != nil { + return m.IsNodeError + } + return false +} + func init() { proto.RegisterType((*CacheRelayReply)(nil), "lavanet.lava.pairing.CacheRelayReply") proto.RegisterType((*CacheUsage)(nil), "lavanet.lava.pairing.CacheUsage") @@ -415,47 +423,49 @@ func init() { } var fileDescriptor_36fbab536e2bbad1 = []byte{ - // 638 bytes of a gzipped FileDescriptorProto + // 662 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcd, 0x6e, 0xd3, 0x40, - 0x10, 0xb6, 0x9b, 0x34, 0x3f, 0x93, 0x96, 0x96, 0x55, 0x85, 0x42, 0x68, 0x8d, 0x31, 0xea, 0xcf, - 0x01, 0xd9, 0x52, 0x91, 0x38, 0x71, 0x80, 0x52, 0xd4, 0x56, 0xa2, 0x12, 0x38, 0x20, 0x21, 0x2e, - 0xd1, 0x26, 0x9e, 0xda, 0x2b, 0x1c, 0xdb, 0x78, 0xb7, 0x15, 0xe5, 0x29, 0x78, 0x1d, 0xc4, 0x0b, - 0xf4, 0xd8, 0x23, 0x27, 0x84, 0xda, 0xa7, 0x80, 0x13, 0xf2, 0xc4, 0x49, 0x93, 0xc8, 0x8d, 0x2a, - 0xc1, 0xc9, 0xde, 0x6f, 0xbf, 0xd9, 0x99, 0xf9, 0xbe, 0xd1, 0xc0, 0x7a, 0xc8, 0x4f, 0x78, 0x84, - 0xca, 0xc9, 0xbe, 0x4e, 0xc2, 0x45, 0x2a, 0x22, 0xdf, 0x49, 0x31, 0xe4, 0xa7, 0x2f, 0x78, 0x2f, - 0x40, 0x3b, 0x49, 0x63, 0x15, 0xb3, 0x95, 0x9c, 0x66, 0x67, 0x5f, 0x3b, 0xa7, 0xb5, 0x56, 0xfc, - 0xd8, 0x8f, 0x89, 0xe0, 0x64, 0x7f, 0x03, 0x6e, 0xcb, 0xbc, 0xfe, 0xc9, 0x9c, 0x71, 0xcf, 0x8f, - 0x63, 0x3f, 0x44, 0x87, 0x4e, 0xdd, 0xe3, 0x23, 0x07, 0xfb, 0x89, 0xca, 0x2f, 0xad, 0xef, 0x3a, - 0x2c, 0x51, 0x6a, 0x37, 0x8b, 0x70, 0x31, 0x09, 0x4f, 0xd9, 0x13, 0x98, 0x4f, 0xb3, 0x9f, 0xa6, - 0x6e, 0xea, 0x5b, 0x8d, 0x6d, 0xd3, 0x2e, 0x2a, 0xc7, 0xbe, 0x0a, 0x70, 0x07, 0x74, 0xf6, 0x06, - 0x6e, 0xc7, 0x89, 0x12, 0x71, 0xc4, 0xc3, 0x4e, 0x1f, 0x15, 0xf7, 0xb8, 0xe2, 0xcd, 0x39, 0xb3, - 0xb4, 0xd5, 0xd8, 0x36, 0x8a, 0xdf, 0x38, 0xcc, 0x59, 0x3b, 0xe5, 0xb3, 0x9f, 0xf7, 0x35, 0x77, - 0x79, 0x18, 0x3e, 0xc4, 0xd9, 0x1a, 0x80, 0x44, 0x8c, 0x3a, 0xdd, 0x30, 0xee, 0x7d, 0x6c, 0x96, - 0x4c, 0x7d, 0xab, 0xe4, 0xd6, 0x33, 0x64, 0x27, 0x03, 0xac, 0x57, 0x00, 0x54, 0xfc, 0x3b, 0xc9, - 0x7d, 0x64, 0xab, 0x50, 0xa7, 0xd3, 0xbe, 0x50, 0x92, 0x6a, 0x2f, 0xbb, 0x57, 0x00, 0x33, 0xa1, - 0x41, 0x87, 0x43, 0x21, 0x25, 0xca, 0xe6, 0x1c, 0xdd, 0x8f, 0x43, 0x56, 0x30, 0x8c, 0xe7, 0x32, - 0x60, 0xcf, 0xa0, 0x9a, 0xe2, 0xa7, 0x63, 0x94, 0x2a, 0x97, 0x61, 0x63, 0x86, 0x0c, 0xaf, 0x53, - 0x71, 0xc2, 0x15, 0xee, 0x72, 0xc5, 0xdd, 0x61, 0x18, 0xbb, 0x0b, 0xb5, 0x5e, 0xc0, 0x45, 0xd4, - 0x11, 0x1e, 0x65, 0xab, 0xbb, 0x55, 0x3a, 0x1f, 0x78, 0xd6, 0x1f, 0x1d, 0x16, 0xdd, 0x91, 0xeb, - 0x7b, 0xa8, 0xd8, 0x03, 0x58, 0xc8, 0xe3, 0x3a, 0x01, 0x97, 0x01, 0xe5, 0x5c, 0x70, 0x1b, 0x39, - 0x46, 0x15, 0xad, 0x01, 0x90, 0x0c, 0x03, 0xc2, 0x1c, 0x11, 0xea, 0x84, 0xd0, 0xf5, 0x2a, 0xd4, - 0x8f, 0x44, 0xc4, 0x43, 0xf1, 0x05, 0x3d, 0x52, 0xaa, 0xe6, 0x5e, 0x01, 0x6c, 0x13, 0x96, 0xf2, - 0xb7, 0xd0, 0xcb, 0xd5, 0x2c, 0x93, 0x9a, 0xb7, 0x46, 0x30, 0x49, 0xca, 0x36, 0x60, 0x49, 0x06, - 0x3c, 0x45, 0xaf, 0x23, 0x15, 0x57, 0x98, 0x15, 0x3f, 0x4f, 0xc5, 0x2f, 0x0e, 0xe0, 0x76, 0x86, - 0x1e, 0x78, 0x13, 0xdd, 0x55, 0x26, 0xba, 0x9b, 0x32, 0xad, 0x3a, 0x6d, 0xda, 0xb7, 0xd2, 0x78, - 0xf3, 0xed, 0xff, 0xd2, 0xfc, 0x53, 0xa8, 0xa5, 0x28, 0x93, 0x38, 0x92, 0x48, 0xbd, 0xdf, 0x64, - 0x6a, 0x47, 0x11, 0x93, 0xd2, 0x95, 0xa7, 0xa5, 0x2b, 0x1c, 0xeb, 0xf9, 0x7f, 0x1a, 0xeb, 0x02, - 0x91, 0x2b, 0x45, 0x22, 0x17, 0xb8, 0x56, 0x2d, 0x74, 0x6d, 0xdc, 0x8d, 0xfa, 0x2c, 0x37, 0x60, - 0xca, 0x0d, 0xf6, 0x08, 0x18, 0x3f, 0xc1, 0x94, 0xfb, 0x38, 0x60, 0x74, 0x94, 0xe8, 0x63, 0xb3, - 0x41, 0xb4, 0xe5, 0xfc, 0x86, 0x98, 0x6f, 0x45, 0x1f, 0xb7, 0x7f, 0xeb, 0xb0, 0x40, 0x12, 0x62, - 0x4a, 0xee, 0xb1, 0xf7, 0x50, 0xdb, 0x43, 0x45, 0x10, 0x7b, 0x38, 0x43, 0xf2, 0xe1, 0xa0, 0xb7, - 0xd6, 0x8b, 0x49, 0x53, 0x3b, 0xc8, 0xd2, 0xd8, 0x01, 0xd4, 0xda, 0x37, 0x7e, 0xb9, 0x8d, 0xaa, - 0x75, 0xc7, 0x1e, 0x2c, 0x3a, 0x7b, 0xb8, 0xe8, 0xec, 0x97, 0xd9, 0xa2, 0xb3, 0x34, 0xb6, 0x0b, - 0x95, 0x7d, 0xe4, 0xa1, 0x0a, 0xd8, 0x35, 0x9c, 0x96, 0x39, 0xa3, 0x2a, 0x5a, 0x2e, 0x96, 0xb6, - 0xf3, 0xfc, 0xec, 0xc2, 0xd0, 0xcf, 0x2f, 0x0c, 0xfd, 0xd7, 0x85, 0xa1, 0x7f, 0xbd, 0x34, 0xb4, - 0xf3, 0x4b, 0x43, 0xfb, 0x71, 0x69, 0x68, 0x1f, 0x36, 0x7d, 0xa1, 0x82, 0xe3, 0xae, 0xdd, 0x8b, - 0xfb, 0xce, 0xc4, 0x3a, 0xfe, 0x3c, 0x5a, 0xc8, 0xea, 0x34, 0x41, 0xd9, 0xad, 0x50, 0xda, 0xc7, - 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x81, 0x66, 0x88, 0xc1, 0x08, 0x06, 0x00, 0x00, + 0x10, 0xb6, 0x9b, 0x34, 0x3f, 0x9b, 0x94, 0x96, 0x55, 0x85, 0x42, 0x68, 0x8d, 0x31, 0xea, 0xcf, + 0x01, 0xd9, 0x52, 0x91, 0x38, 0x71, 0x80, 0xd2, 0xaa, 0xad, 0x44, 0x11, 0x38, 0x20, 0x21, 0x2e, + 0xd6, 0x26, 0x9e, 0xda, 0x2b, 0x1c, 0xaf, 0xf1, 0x6e, 0x2b, 0xca, 0x53, 0xf0, 0x3e, 0xbc, 0x40, + 0x8f, 0x3d, 0x72, 0x01, 0xa1, 0xf6, 0x29, 0xe0, 0x84, 0x3c, 0x71, 0xd2, 0x24, 0x72, 0xa3, 0x4a, + 0x70, 0xf2, 0xee, 0xb7, 0xdf, 0xec, 0xcc, 0x7c, 0xdf, 0x7a, 0xc8, 0x5a, 0xc4, 0x4e, 0x58, 0x0c, + 0xca, 0xc9, 0xbe, 0x4e, 0xc2, 0x78, 0xca, 0xe3, 0xc0, 0x49, 0x21, 0x62, 0xa7, 0x2f, 0x58, 0x2f, + 0x04, 0x3b, 0x49, 0x85, 0x12, 0x74, 0x39, 0xa7, 0xd9, 0xd9, 0xd7, 0xce, 0x69, 0xed, 0xe5, 0x40, + 0x04, 0x02, 0x09, 0x4e, 0xb6, 0x1a, 0x70, 0xdb, 0xe6, 0xf5, 0x57, 0xe6, 0x8c, 0x7b, 0x81, 0x10, + 0x41, 0x04, 0x0e, 0xee, 0xba, 0xc7, 0x47, 0x0e, 0xf4, 0x13, 0x95, 0x1f, 0x5a, 0xdf, 0x74, 0xb2, + 0x88, 0xa9, 0xdd, 0x2c, 0xc2, 0x85, 0x24, 0x3a, 0xa5, 0x4f, 0xc8, 0x7c, 0x9a, 0x2d, 0x5a, 0xba, + 0xa9, 0x6f, 0x36, 0xb6, 0x4c, 0xbb, 0xa8, 0x1c, 0xfb, 0x2a, 0xc0, 0x1d, 0xd0, 0xe9, 0x1b, 0x72, + 0x5b, 0x24, 0x8a, 0x8b, 0x98, 0x45, 0x5e, 0x1f, 0x14, 0xf3, 0x99, 0x62, 0xad, 0x39, 0xb3, 0xb4, + 0xd9, 0xd8, 0x32, 0x8a, 0xef, 0x38, 0xcc, 0x59, 0xdb, 0xe5, 0xb3, 0x9f, 0xf7, 0x35, 0x77, 0x69, + 0x18, 0x3e, 0xc4, 0xe9, 0x2a, 0x21, 0x12, 0x20, 0xf6, 0xba, 0x91, 0xe8, 0x7d, 0x6c, 0x95, 0x4c, + 0x7d, 0xb3, 0xe4, 0xd6, 0x33, 0x64, 0x3b, 0x03, 0xac, 0x97, 0x84, 0x60, 0xf1, 0xef, 0x24, 0x0b, + 0x80, 0xae, 0x90, 0x3a, 0xee, 0xf6, 0xb9, 0x92, 0x58, 0x7b, 0xd9, 0xbd, 0x02, 0xa8, 0x49, 0x1a, + 0xb8, 0x39, 0xe4, 0x52, 0x82, 0x6c, 0xcd, 0xe1, 0xf9, 0x38, 0x64, 0x85, 0xc3, 0x78, 0x26, 0x43, + 0xfa, 0x8c, 0x54, 0x53, 0xf8, 0x74, 0x0c, 0x52, 0xe5, 0x32, 0xac, 0xcf, 0x90, 0xe1, 0x75, 0xca, + 0x4f, 0x98, 0x82, 0x1d, 0xa6, 0x98, 0x3b, 0x0c, 0xa3, 0x77, 0x49, 0xad, 0x17, 0x32, 0x1e, 0x7b, + 0xdc, 0xc7, 0x6c, 0x75, 0xb7, 0x8a, 0xfb, 0x03, 0xdf, 0xfa, 0xa3, 0x93, 0x05, 0x77, 0xe4, 0xfa, + 0x1e, 0x28, 0xfa, 0x80, 0x34, 0xf3, 0x38, 0x2f, 0x64, 0x32, 0xc4, 0x9c, 0x4d, 0xb7, 0x91, 0x63, + 0x58, 0xd1, 0x2a, 0x21, 0x28, 0xc3, 0x80, 0x30, 0x87, 0x84, 0x3a, 0x22, 0x78, 0xbc, 0x42, 0xea, + 0x47, 0x3c, 0x66, 0x11, 0xff, 0x02, 0x3e, 0x2a, 0x55, 0x73, 0xaf, 0x00, 0xba, 0x41, 0x16, 0xf3, + 0xbb, 0xc0, 0xcf, 0xd5, 0x2c, 0xa3, 0x9a, 0xb7, 0x46, 0x30, 0x4a, 0x4a, 0xd7, 0xc9, 0xa2, 0x0c, + 0x59, 0x0a, 0xbe, 0x27, 0x15, 0x53, 0x90, 0x15, 0x3f, 0x8f, 0xc5, 0x2f, 0x0c, 0xe0, 0x4e, 0x86, + 0x1e, 0xf8, 0x13, 0xdd, 0x55, 0x26, 0xba, 0x9b, 0x32, 0xad, 0x3a, 0x6d, 0xda, 0x8f, 0xd2, 0x78, + 0xf3, 0x9d, 0xff, 0xd2, 0xfc, 0x53, 0x52, 0x4b, 0x41, 0x26, 0x22, 0x96, 0x80, 0xbd, 0xdf, 0xe4, + 0xd5, 0x8e, 0x22, 0x26, 0xa5, 0x2b, 0x4f, 0x4b, 0x57, 0xf8, 0xac, 0xe7, 0xff, 0xe9, 0x59, 0x17, + 0x88, 0x5c, 0x29, 0x12, 0xb9, 0xc0, 0xb5, 0x6a, 0xa1, 0x6b, 0xe3, 0x6e, 0xd4, 0x67, 0xb9, 0x41, + 0xa6, 0xdc, 0xa0, 0x8f, 0x08, 0x65, 0x27, 0x90, 0xb2, 0x00, 0x06, 0x0c, 0x4f, 0xf1, 0x3e, 0xb4, + 0x1a, 0x48, 0x5b, 0xca, 0x4f, 0x90, 0xf9, 0x96, 0xf7, 0x81, 0x5a, 0x64, 0x81, 0x4b, 0x2f, 0x16, + 0x3e, 0x78, 0x90, 0xa6, 0x22, 0x6d, 0x35, 0x51, 0xad, 0x06, 0x97, 0xaf, 0x84, 0x0f, 0xbb, 0x19, + 0xb4, 0xf5, 0x5b, 0x27, 0x4d, 0x94, 0x19, 0x52, 0x74, 0x98, 0xbe, 0x27, 0xb5, 0x3d, 0x50, 0x08, + 0xd1, 0x87, 0x33, 0x6c, 0x19, 0xfe, 0x0c, 0xed, 0xb5, 0x62, 0xd2, 0xd4, 0x9c, 0xb2, 0x34, 0x7a, + 0x40, 0x6a, 0x9d, 0x1b, 0xdf, 0xdc, 0x01, 0xd5, 0xbe, 0x63, 0x0f, 0x86, 0xa1, 0x3d, 0x1c, 0x86, + 0xf6, 0x6e, 0x36, 0x0c, 0x2d, 0x8d, 0xee, 0x90, 0xca, 0x3e, 0xb0, 0x48, 0x85, 0xf4, 0x1a, 0x4e, + 0xdb, 0x9c, 0x51, 0x15, 0x0e, 0x20, 0x4b, 0xdb, 0x7e, 0x7e, 0x76, 0x61, 0xe8, 0xe7, 0x17, 0x86, + 0xfe, 0xeb, 0xc2, 0xd0, 0xbf, 0x5e, 0x1a, 0xda, 0xf9, 0xa5, 0xa1, 0x7d, 0xbf, 0x34, 0xb4, 0x0f, + 0x1b, 0x01, 0x57, 0xe1, 0x71, 0xd7, 0xee, 0x89, 0xbe, 0x33, 0x31, 0xb2, 0x3f, 0x8f, 0x86, 0xb6, + 0x3a, 0x4d, 0x40, 0x76, 0x2b, 0x98, 0xf6, 0xf1, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x1c, + 0xe5, 0x7f, 0x2c, 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -830,6 +840,16 @@ func (m *RelayCacheSet) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.IsNodeError { + i-- + if m.IsNodeError { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x60 + } if m.AverageBlockTime != 0 { i = encodeVarintRelayCache(dAtA, i, uint64(m.AverageBlockTime)) i-- @@ -1055,6 +1075,9 @@ func (m *RelayCacheSet) Size() (n int) { if m.AverageBlockTime != 0 { n += 1 + sovRelayCache(uint64(m.AverageBlockTime)) } + if m.IsNodeError { + n += 2 + } return n } @@ -1957,6 +1980,26 @@ func (m *RelayCacheSet) Unmarshal(dAtA []byte) error { break } } + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field IsNodeError", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRelayCache + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.IsNodeError = bool(v != 0) default: iNdEx = preIndex skippy, err := skipRelayCache(dAtA[iNdEx:]) diff --git a/x/protocol/types/params.go b/x/protocol/types/params.go index 72bdf82a5d..a508cf486c 100644 --- a/x/protocol/types/params.go +++ b/x/protocol/types/params.go @@ -12,7 +12,7 @@ import ( var _ paramtypes.ParamSet = (*Params)(nil) const ( - TARGET_VERSION = "1.2.4" + TARGET_VERSION = "1.2.5" MIN_VERSION = "1.0.2" )