feat: zilliqa consensus data related to block (#10699)
* refactor: DRY declaration of chain type and feature dependent repos * feat: add `:zilliqa` chain type * chore: add `zilliqa` to cspell.json * feat: import consensus data related to block * fix: cspell * fix: ethereum_jsonrpc tests * fix: format & credo * feat: render consensus data in `/api/v2/blocks/:block_hash_or_number` response * fix: add missing `view` field to block db schema * feat: add workflow to publish docker image * fix: cast `zilliqa_view` field of a block * refactor: view * refactor: define spec only once * refactor: DRY definition of other repos * fix: remove not null constraint for `zilliqa_view` * fix: dialyzer * fix: `@spec` for `chain_type_fields/2` * feat: github workflows * fix: debug * fix: add missing indexer and API workflowspull/11144/head
parent
94745592ac
commit
0dfd4c6ca2
@ -0,0 +1,167 @@ |
|||||||
|
name: Pre-release for Zilliqa |
||||||
|
|
||||||
|
on: |
||||||
|
workflow_dispatch: |
||||||
|
inputs: |
||||||
|
number: |
||||||
|
type: number |
||||||
|
required: true |
||||||
|
|
||||||
|
env: |
||||||
|
OTP_VERSION: ${{ vars.OTP_VERSION }} |
||||||
|
ELIXIR_VERSION: ${{ vars.ELIXIR_VERSION }} |
||||||
|
|
||||||
|
jobs: |
||||||
|
push_to_registry: |
||||||
|
name: Push Docker image to Docker Hub |
||||||
|
runs-on: ubuntu-latest |
||||||
|
env: |
||||||
|
RELEASE_VERSION: 6.9.0 |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v4 |
||||||
|
- name: Setup repo |
||||||
|
uses: ./.github/actions/setup-repo |
||||||
|
id: setup |
||||||
|
with: |
||||||
|
docker-username: ${{ secrets.DOCKER_USERNAME }} |
||||||
|
docker-password: ${{ secrets.DOCKER_PASSWORD }} |
||||||
|
docker-remote-multi-platform: true |
||||||
|
docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} |
||||||
|
docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer + API) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
DISABLE_WEBAPP=false |
||||||
|
API_V1_READ_METHODS_DISABLED=false |
||||||
|
API_V1_WRITE_METHODS_DISABLED=false |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
DISABLE_API=true |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
|
||||||
|
- name: Build and push Docker image (API) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-api |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
DISABLE_INDEXER=true |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer + API + shrink internal transactions) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-shrink-internal-txs |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
API_V1_READ_METHODS_DISABLED=false |
||||||
|
DISABLE_WEBAPP=false |
||||||
|
API_V1_WRITE_METHODS_DISABLED=false |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
SHRINK_INTERNAL_TRANSACTIONS_ENABLED=true |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer + shrink internal transactions) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-shrink-internal-txs-indexer |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
DISABLE_API=true |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
SHRINK_INTERNAL_TRANSACTIONS_ENABLED=true |
||||||
|
|
||||||
|
- name: Build and push Docker image (API + shrink internal transactions) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-shrink-internal-txs-api |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
DISABLE_INDEXER=true |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
SHRINK_INTERNAL_TRANSACTIONS_ENABLED=true |
@ -0,0 +1,162 @@ |
|||||||
|
name: Zilliqa publish Docker image |
||||||
|
|
||||||
|
on: |
||||||
|
workflow_dispatch: |
||||||
|
push: |
||||||
|
branches: |
||||||
|
- production-zilliqa |
||||||
|
jobs: |
||||||
|
push_to_registry: |
||||||
|
name: Push Docker image to Docker Hub |
||||||
|
runs-on: ubuntu-latest |
||||||
|
env: |
||||||
|
RELEASE_VERSION: 6.9.0 |
||||||
|
DOCKER_CHAIN_NAME: zilliqa |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v4 |
||||||
|
- name: Setup repo |
||||||
|
uses: ./.github/actions/setup-repo |
||||||
|
id: setup |
||||||
|
with: |
||||||
|
docker-username: ${{ secrets.DOCKER_USERNAME }} |
||||||
|
docker-password: ${{ secrets.DOCKER_PASSWORD }} |
||||||
|
docker-remote-multi-platform: true |
||||||
|
docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} |
||||||
|
docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer + API) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
API_V1_READ_METHODS_DISABLED=false |
||||||
|
DISABLE_WEBAPP=false |
||||||
|
API_V1_WRITE_METHODS_DISABLED=false |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta.+commit.${{ env.SHORT_SHA }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
DISABLE_API=true |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta.+commit.${{ env.SHORT_SHA }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} |
||||||
|
|
||||||
|
- name: Build and push Docker image (API) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-api |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
DISABLE_INDEXER=true |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta.+commit.${{ env.SHORT_SHA }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer + API + shrink internal transactions) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-shrink-internal-txs |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
API_V1_READ_METHODS_DISABLED=false |
||||||
|
DISABLE_WEBAPP=false |
||||||
|
API_V1_WRITE_METHODS_DISABLED=false |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta.+commit.${{ env.SHORT_SHA }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} |
||||||
|
SHRINK_INTERNAL_TRANSACTIONS_ENABLED=true |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer + shrink internal transactions) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-shrink-internal-txs-indexer |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
DISABLE_API=true |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta.+commit.${{ env.SHORT_SHA }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} |
||||||
|
SHRINK_INTERNAL_TRANSACTIONS_ENABLED=true |
||||||
|
|
||||||
|
- name: Build and push Docker image (API + shrink internal transactions) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-shrink-internal-txs-api |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
DISABLE_INDEXER=true |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta.+commit.${{ env.SHORT_SHA }} |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} |
||||||
|
SHRINK_INTERNAL_TRANSACTIONS_ENABLED=true |
@ -0,0 +1,164 @@ |
|||||||
|
name: Release for Zilliqa |
||||||
|
|
||||||
|
on: |
||||||
|
release: |
||||||
|
types: [published] |
||||||
|
|
||||||
|
env: |
||||||
|
OTP_VERSION: ${{ vars.OTP_VERSION }} |
||||||
|
ELIXIR_VERSION: ${{ vars.ELIXIR_VERSION }} |
||||||
|
|
||||||
|
jobs: |
||||||
|
push_to_registry: |
||||||
|
name: Push Docker image to Docker Hub |
||||||
|
runs-on: ubuntu-latest |
||||||
|
env: |
||||||
|
RELEASE_VERSION: 6.9.0 |
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v4 |
||||||
|
- name: Setup repo |
||||||
|
uses: ./.github/actions/setup-repo |
||||||
|
id: setup |
||||||
|
with: |
||||||
|
docker-username: ${{ secrets.DOCKER_USERNAME }} |
||||||
|
docker-password: ${{ secrets.DOCKER_PASSWORD }} |
||||||
|
docker-remote-multi-platform: true |
||||||
|
docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} |
||||||
|
docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer + API) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:latest, blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }} |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
DISABLE_WEBAPP=false |
||||||
|
API_V1_READ_METHODS_DISABLED=false |
||||||
|
API_V1_WRITE_METHODS_DISABLED=false |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }}-indexer |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
DISABLE_API=true |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
|
||||||
|
- name: Build and push Docker image (API) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }}-api |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
DISABLE_INDEXER=true |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer + API + shrink internal transactions) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }}-shrink-internal-txs |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
API_V1_READ_METHODS_DISABLED=false |
||||||
|
DISABLE_WEBAPP=false |
||||||
|
API_V1_WRITE_METHODS_DISABLED=false |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
SHRINK_INTERNAL_TRANSACTIONS_ENABLED=true |
||||||
|
|
||||||
|
- name: Build and push Docker image (indexer + shrink internal transactions) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }}-shrink-internal-txs-indexer |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
DISABLE_API=true |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
SHRINK_INTERNAL_TRANSACTIONS_ENABLED=true |
||||||
|
|
||||||
|
- name: Build and push Docker image (API + shrink internal transactions) |
||||||
|
uses: docker/build-push-action@v5 |
||||||
|
with: |
||||||
|
context: . |
||||||
|
file: ./docker/Dockerfile |
||||||
|
push: true |
||||||
|
tags: blockscout/blockscout-zilliqa:${{ env.RELEASE_VERSION }}-shrink-internal-txs-api |
||||||
|
labels: ${{ steps.setup.outputs.docker-labels }} |
||||||
|
platforms: | |
||||||
|
linux/amd64 |
||||||
|
linux/arm64/v8 |
||||||
|
build-args: | |
||||||
|
CACHE_EXCHANGE_RATES_PERIOD= |
||||||
|
DISABLE_WEBAPP=true |
||||||
|
DISABLE_INDEXER=true |
||||||
|
CACHE_TOTAL_GAS_USAGE_COUNTER_ENABLED= |
||||||
|
ADMIN_PANEL_ENABLED=false |
||||||
|
CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL= |
||||||
|
BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-beta |
||||||
|
RELEASE_VERSION=${{ env.RELEASE_VERSION }} |
||||||
|
CHAIN_TYPE=zilliqa |
||||||
|
SHRINK_INTERNAL_TRANSACTIONS_ENABLED=true |
@ -0,0 +1,88 @@ |
|||||||
|
if Application.compile_env(:explorer, :chain_type) == :zilliqa do |
||||||
|
defmodule BlockScoutWeb.API.V2.ZilliqaView do |
||||||
|
@moduledoc """ |
||||||
|
View functions for rendering Zilliqa-related data in JSON format. |
||||||
|
""" |
||||||
|
|
||||||
|
alias Explorer.Chain.Block |
||||||
|
alias Explorer.Chain.Zilliqa.{AggregateQuorumCertificate, QuorumCertificate} |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Extends the JSON output with a sub-map containing information related to Zilliqa, |
||||||
|
such as the quorum certificate and aggregate quorum certificate. |
||||||
|
|
||||||
|
## Parameters |
||||||
|
- `out_json`: A map defining the output JSON which will be extended. |
||||||
|
- `block`: The block structure containing Zilliqa-related data. |
||||||
|
- `single_block?`: A boolean indicating if it is a single block. |
||||||
|
|
||||||
|
## Returns |
||||||
|
- A map extended with data related to Zilliqa. |
||||||
|
""" |
||||||
|
@spec extend_block_json_response(map(), Block.t(), boolean()) :: map() |
||||||
|
def extend_block_json_response(out_json, %Block{}, false), |
||||||
|
do: out_json |
||||||
|
|
||||||
|
def extend_block_json_response(out_json, %Block{zilliqa_view: zilliqa_view} = block, true) do |
||||||
|
zilliqa_json = |
||||||
|
%{view: zilliqa_view} |
||||||
|
|> add_quorum_certificate(block) |
||||||
|
|> add_aggregate_quorum_certificate(block) |
||||||
|
|
||||||
|
Map.put(out_json, :zilliqa, zilliqa_json) |
||||||
|
end |
||||||
|
|
||||||
|
@spec add_quorum_certificate(map(), Block.t()) :: map() |
||||||
|
defp add_quorum_certificate( |
||||||
|
zilliqa_json, |
||||||
|
%Block{ |
||||||
|
zilliqa_quorum_certificate: %QuorumCertificate{ |
||||||
|
view: view, |
||||||
|
signature: signature, |
||||||
|
signers: signers |
||||||
|
} |
||||||
|
} |
||||||
|
) do |
||||||
|
zilliqa_json |
||||||
|
|> Map.put(:quorum_certificate, %{ |
||||||
|
view: view, |
||||||
|
signature: signature, |
||||||
|
signers: signers |
||||||
|
}) |
||||||
|
end |
||||||
|
|
||||||
|
defp add_quorum_certificate(zilliqa_json, _block), do: zilliqa_json |
||||||
|
|
||||||
|
@spec add_aggregate_quorum_certificate(map(), Block.t()) :: map() |
||||||
|
defp add_aggregate_quorum_certificate(zilliqa_json, %Block{ |
||||||
|
zilliqa_aggregate_quorum_certificate: %AggregateQuorumCertificate{ |
||||||
|
view: view, |
||||||
|
signature: signature, |
||||||
|
nested_quorum_certificates: nested_quorum_certificates |
||||||
|
} |
||||||
|
}) |
||||||
|
when is_list(nested_quorum_certificates) do |
||||||
|
zilliqa_json |
||||||
|
|> Map.put(:aggregate_quorum_certificate, %{ |
||||||
|
view: view, |
||||||
|
signature: signature, |
||||||
|
signers: |
||||||
|
Enum.map( |
||||||
|
nested_quorum_certificates, |
||||||
|
& &1.proposed_by_validator_index |
||||||
|
), |
||||||
|
nested_quorum_certificates: |
||||||
|
Enum.map( |
||||||
|
nested_quorum_certificates, |
||||||
|
&%{ |
||||||
|
view: &1.view, |
||||||
|
signature: &1.signature, |
||||||
|
proposed_by_validator_index: &1.proposed_by_validator_index |
||||||
|
} |
||||||
|
) |
||||||
|
}) |
||||||
|
end |
||||||
|
|
||||||
|
defp add_aggregate_quorum_certificate(zilliqa_json, _block), do: zilliqa_json |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,20 @@ |
|||||||
|
defmodule EthereumJSONRPC.Zilliqa do |
||||||
|
@moduledoc """ |
||||||
|
Zilliqa type definitions. |
||||||
|
""" |
||||||
|
alias EthereumJSONRPC.Zilliqa.{ |
||||||
|
AggregateQuorumCertificate, |
||||||
|
NestedQuorumCertificates, |
||||||
|
QuorumCertificate |
||||||
|
} |
||||||
|
|
||||||
|
@type consensus_data_params :: %{ |
||||||
|
zilliqa_quorum_certificates_params: [QuorumCertificate.params()], |
||||||
|
zilliqa_aggregate_quorum_certificates_params: [AggregateQuorumCertificate.params()], |
||||||
|
zilliqa_nested_quorum_certificates_params: [NestedQuorumCertificates.params()] |
||||||
|
} |
||||||
|
|
||||||
|
@type bit_vector :: String.t() |
||||||
|
@type validator_index :: non_neg_integer() |
||||||
|
@type signers :: [validator_index()] |
||||||
|
end |
@ -0,0 +1,186 @@ |
|||||||
|
defmodule EthereumJSONRPC.Zilliqa.AggregateQuorumCertificate do |
||||||
|
@moduledoc """ |
||||||
|
Represents an aggregate quorum certificate associated with the block. |
||||||
|
""" |
||||||
|
import EthereumJSONRPC, only: [quantity_to_integer: 1] |
||||||
|
|
||||||
|
alias EthereumJSONRPC.Zilliqa.NestedQuorumCertificates |
||||||
|
|
||||||
|
@type elixir :: %{ |
||||||
|
String.t() => |
||||||
|
EthereumJSONRPC.quantity() |
||||||
|
| EthereumJSONRPC.hash() |
||||||
|
| EthereumJSONRPC.Zilliqa.bit_vector() |
||||||
|
| NestedQuorumCertificates.elixir() |
||||||
|
} |
||||||
|
|
||||||
|
@type t :: %__MODULE__{ |
||||||
|
block_hash: EthereumJSONRPC.hash(), |
||||||
|
view: non_neg_integer(), |
||||||
|
signature: EthereumJSONRPC.hash(), |
||||||
|
quorum_certificates: NestedQuorumCertificates.t() |
||||||
|
} |
||||||
|
|
||||||
|
@type params :: %{ |
||||||
|
block_hash: EthereumJSONRPC.hash(), |
||||||
|
view: non_neg_integer(), |
||||||
|
signature: EthereumJSONRPC.hash() |
||||||
|
} |
||||||
|
|
||||||
|
defstruct [:block_hash, :view, :signature, :quorum_certificates] |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Decodes the JSON object returned by JSONRPC node into the `t:t/0` format. |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
iex> aqc_json = %{ |
||||||
|
...> "cosigned" => "[0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", |
||||||
|
...> "quorum_certificates" => [ |
||||||
|
...> %{ |
||||||
|
...> "block_hash" => "0x4b8939a7fb0d7de4b288bafd4d5caa02f53abf3c1e348fca5038eebbf68248fa", |
||||||
|
...> "cosigned" => "[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", |
||||||
|
...> "signature" => "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> "view" => "0x115cc7" |
||||||
|
...> }, |
||||||
|
...> %{ |
||||||
|
...> "block_hash" => "0x4b8939a7fb0d7de4b288bafd4d5caa02f53abf3c1e348fca5038eebbf68248fa", |
||||||
|
...> "cosigned" => "[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", |
||||||
|
...> "signature" => "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> "view" => "0x115cc7" |
||||||
|
...> }, |
||||||
|
...> %{ |
||||||
|
...> "block_hash" => "0x4b8939a7fb0d7de4b288bafd4d5caa02f53abf3c1e348fca5038eebbf68248fa", |
||||||
|
...> "cosigned" => "[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", |
||||||
|
...> "signature" => "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> "view" => "0x115cc7" |
||||||
|
...> }, |
||||||
|
...> %{ |
||||||
|
...> "block_hash" => "0x4b8939a7fb0d7de4b288bafd4d5caa02f53abf3c1e348fca5038eebbf68248fa", |
||||||
|
...> "cosigned" => "[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", |
||||||
|
...> "signature" => "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> "view" => "0x115cc7" |
||||||
|
...> } |
||||||
|
...> ], |
||||||
|
...> "signature" => "0x820f591cd78b29a69ba25bc85c4327fa3b0adb61a73a4f0bd943b4ab0b97e061eae9ac032d19fbfab7efb89fac2454ab0b89fea83185c0dac749ff55b0e2c21535a2b712872491577728db868d11939461a6bfde0d94d238f46b643bbe19767e", |
||||||
|
...> "view" => "0x115cca" |
||||||
|
...> } |
||||||
|
iex> block_hash = "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d" |
||||||
|
iex> EthereumJSONRPC.Zilliqa.AggregateQuorumCertificate.new(aqc_json, block_hash) |
||||||
|
%EthereumJSONRPC.Zilliqa.AggregateQuorumCertificate{ |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137866, |
||||||
|
signature: "0x820f591cd78b29a69ba25bc85c4327fa3b0adb61a73a4f0bd943b4ab0b97e061eae9ac032d19fbfab7efb89fac2454ab0b89fea83185c0dac749ff55b0e2c21535a2b712872491577728db868d11939461a6bfde0d94d238f46b643bbe19767e", |
||||||
|
quorum_certificates: %EthereumJSONRPC.Zilliqa.NestedQuorumCertificates{ |
||||||
|
signers: [1, 2, 3, 8], |
||||||
|
items: [ |
||||||
|
%EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
signers: [0, 1, 3, 8] |
||||||
|
}, |
||||||
|
%EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
signers: [0, 1, 3, 8] |
||||||
|
}, |
||||||
|
%EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
signers: [0, 1, 3, 8] |
||||||
|
}, |
||||||
|
%EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
signers: [0, 1, 3, 8] |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
} |
||||||
|
""" |
||||||
|
@spec new(elixir(), EthereumJSONRPC.hash()) :: t() |
||||||
|
def new( |
||||||
|
%{ |
||||||
|
"view" => view, |
||||||
|
"signature" => signature, |
||||||
|
"cosigned" => bit_vector, |
||||||
|
"quorum_certificates" => quorum_certificates |
||||||
|
}, |
||||||
|
block_hash |
||||||
|
) do |
||||||
|
%__MODULE__{ |
||||||
|
block_hash: block_hash, |
||||||
|
view: quantity_to_integer(view), |
||||||
|
signature: signature, |
||||||
|
quorum_certificates: |
||||||
|
NestedQuorumCertificates.new( |
||||||
|
quorum_certificates, |
||||||
|
bit_vector, |
||||||
|
block_hash |
||||||
|
) |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Converts `t:t/0` format to params used in `Explorer.Chain`. |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
iex> aggregate_quorum_certificate = %EthereumJSONRPC.Zilliqa.AggregateQuorumCertificate{ |
||||||
|
...> block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
...> view: 1137866, |
||||||
|
...> signature: "0x820f591cd78b29a69ba25bc85c4327fa3b0adb61a73a4f0bd943b4ab0b97e061eae9ac032d19fbfab7efb89fac2454ab0b89fea83185c0dac749ff55b0e2c21535a2b712872491577728db868d11939461a6bfde0d94d238f46b643bbe19767e", |
||||||
|
...> quorum_certificates: %EthereumJSONRPC.Zilliqa.NestedQuorumCertificates{ |
||||||
|
...> signers: [1, 2, 3, 8], |
||||||
|
...> items: [ |
||||||
|
...> %EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
...> block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
...> view: 1137863, |
||||||
|
...> signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> signers: [0, 1, 3, 8] |
||||||
|
...> }, |
||||||
|
...> %EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
...> block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
...> view: 1137863, |
||||||
|
...> signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> signers: [0, 1, 3, 8] |
||||||
|
...> }, |
||||||
|
...> %EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
...> block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
...> view: 1137863, |
||||||
|
...> signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> signers: [0, 1, 3, 8] |
||||||
|
...> }, |
||||||
|
...> %EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
...> block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
...> view: 1137863, |
||||||
|
...> signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> signers: [0, 1, 3, 8] |
||||||
|
...> } |
||||||
|
...> ] |
||||||
|
...> } |
||||||
|
...> } |
||||||
|
iex> EthereumJSONRPC.Zilliqa.AggregateQuorumCertificate.to_params(aggregate_quorum_certificate) |
||||||
|
%{ |
||||||
|
signature: "0x820f591cd78b29a69ba25bc85c4327fa3b0adb61a73a4f0bd943b4ab0b97e061eae9ac032d19fbfab7efb89fac2454ab0b89fea83185c0dac749ff55b0e2c21535a2b712872491577728db868d11939461a6bfde0d94d238f46b643bbe19767e", |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137866 |
||||||
|
} |
||||||
|
""" |
||||||
|
@spec to_params(t()) :: params() |
||||||
|
def to_params(%__MODULE__{ |
||||||
|
block_hash: block_hash, |
||||||
|
view: view, |
||||||
|
signature: signature |
||||||
|
}) do |
||||||
|
%{ |
||||||
|
block_hash: block_hash, |
||||||
|
view: view, |
||||||
|
signature: signature |
||||||
|
} |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,111 @@ |
|||||||
|
defmodule EthereumJSONRPC.Zilliqa.Helper do |
||||||
|
@moduledoc """ |
||||||
|
Helper functions for processing consensus data. |
||||||
|
""" |
||||||
|
alias EthereumJSONRPC.Zilliqa |
||||||
|
alias EthereumJSONRPC.{Block, Blocks} |
||||||
|
|
||||||
|
alias EthereumJSONRPC.Zilliqa.{ |
||||||
|
AggregateQuorumCertificate, |
||||||
|
NestedQuorumCertificates, |
||||||
|
QuorumCertificate |
||||||
|
} |
||||||
|
|
||||||
|
@initial_acc %{ |
||||||
|
zilliqa_quorum_certificates_params: [], |
||||||
|
zilliqa_aggregate_quorum_certificates_params: [], |
||||||
|
zilliqa_nested_quorum_certificates_params: [] |
||||||
|
} |
||||||
|
|
||||||
|
@type consensus_data_params :: %{ |
||||||
|
zilliqa_quorum_certificates_params: [QuorumCertificate.params()], |
||||||
|
zilliqa_aggregate_quorum_certificates_params: [AggregateQuorumCertificate.params()], |
||||||
|
zilliqa_nested_quorum_certificates_params: [NestedQuorumCertificates.params()] |
||||||
|
} |
||||||
|
|
||||||
|
@spec extend_blocks_struct(Blocks.t(), Blocks.elixir()) :: Blocks.t() |
||||||
|
def extend_blocks_struct(%Blocks{} = module, elixir_blocks) do |
||||||
|
consensus_data_fields = |
||||||
|
Enum.reduce( |
||||||
|
elixir_blocks, |
||||||
|
@initial_acc, |
||||||
|
&reduce_to_consensus_data/2 |
||||||
|
) |
||||||
|
|
||||||
|
Map.merge(module, consensus_data_fields) |
||||||
|
end |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Converts a bit vector string to a list of indexes where the bit corresponding |
||||||
|
to signing validator is 1. |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
iex> bit_vector_to_signers("[1, 0, 1, 0]") |
||||||
|
[0, 2] |
||||||
|
|
||||||
|
iex> bit_vector_to_signers("[1, 1, 1, 1]") |
||||||
|
[0, 1, 2, 3] |
||||||
|
""" |
||||||
|
@spec bit_vector_to_signers(Zilliqa.bit_vector()) :: Zilliqa.signers() |
||||||
|
def bit_vector_to_signers(bit_vector_string) do |
||||||
|
bit_vector_string |
||||||
|
|> Jason.decode!() |
||||||
|
|> Enum.with_index() |
||||||
|
|> Enum.filter(fn {bit, _} -> bit == 1 end) |
||||||
|
|> Enum.map(fn {_, index} -> index end) |
||||||
|
end |
||||||
|
|
||||||
|
@spec reduce_to_consensus_data( |
||||||
|
Block.elixir(), |
||||||
|
consensus_data_params() |
||||||
|
) :: consensus_data_params() |
||||||
|
defp reduce_to_consensus_data( |
||||||
|
elixir_block, |
||||||
|
%{ |
||||||
|
zilliqa_quorum_certificates_params: quorum_certificates_params_acc, |
||||||
|
zilliqa_aggregate_quorum_certificates_params: aggregate_quorum_certificates_params_acc, |
||||||
|
zilliqa_nested_quorum_certificates_params: aggregate_nested_quorum_certificates_params_acc |
||||||
|
} |
||||||
|
) do |
||||||
|
quorum_certificates_map = |
||||||
|
elixir_block |
||||||
|
|> Block.elixir_to_zilliqa_quorum_certificate() |
||||||
|
|> case do |
||||||
|
nil -> |
||||||
|
%{zilliqa_quorum_certificates_params: quorum_certificates_params_acc} |
||||||
|
|
||||||
|
quorum_certificate -> |
||||||
|
quorum_certificate_params = QuorumCertificate.to_params(quorum_certificate) |
||||||
|
%{zilliqa_quorum_certificates_params: [quorum_certificate_params | quorum_certificates_params_acc]} |
||||||
|
end |
||||||
|
|
||||||
|
aggregated_quorum_certificate_map = |
||||||
|
elixir_block |
||||||
|
|> Block.elixir_to_zilliqa_aggregate_quorum_certificate() |
||||||
|
|> case do |
||||||
|
nil -> |
||||||
|
%{ |
||||||
|
zilliqa_aggregate_quorum_certificates_params: aggregate_quorum_certificates_params_acc, |
||||||
|
zilliqa_nested_quorum_certificates_params: aggregate_nested_quorum_certificates_params_acc |
||||||
|
} |
||||||
|
|
||||||
|
aggregate_quorum_certificates -> |
||||||
|
aggregate_quorum_certificate_params = |
||||||
|
AggregateQuorumCertificate.to_params(aggregate_quorum_certificates) |
||||||
|
|
||||||
|
aggregate_nested_quorum_certificates_params = |
||||||
|
NestedQuorumCertificates.to_params(aggregate_quorum_certificates.quorum_certificates) |
||||||
|
|
||||||
|
%{ |
||||||
|
zilliqa_aggregate_quorum_certificates_params: [ |
||||||
|
aggregate_quorum_certificate_params | aggregate_quorum_certificates_params_acc |
||||||
|
], |
||||||
|
zilliqa_nested_quorum_certificates_params: |
||||||
|
aggregate_nested_quorum_certificates_params ++ aggregate_nested_quorum_certificates_params_acc |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
Map.merge(quorum_certificates_map, aggregated_quorum_certificate_map) |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,187 @@ |
|||||||
|
defmodule EthereumJSONRPC.Zilliqa.NestedQuorumCertificates do |
||||||
|
@moduledoc """ |
||||||
|
Represents a list of quorum certificates that were proposed by different |
||||||
|
validators in the aggregate quorum certificate. |
||||||
|
""" |
||||||
|
|
||||||
|
import EthereumJSONRPC.Zilliqa.Helper, |
||||||
|
only: [bit_vector_to_signers: 1] |
||||||
|
|
||||||
|
alias EthereumJSONRPC.Zilliqa |
||||||
|
alias EthereumJSONRPC.Zilliqa.QuorumCertificate |
||||||
|
|
||||||
|
defstruct [:signers, :items] |
||||||
|
|
||||||
|
@type elixir :: [QuorumCertificate.elixir()] |
||||||
|
|
||||||
|
@type t :: %__MODULE__{ |
||||||
|
signers: [non_neg_integer()], |
||||||
|
items: [QuorumCertificate.t()] |
||||||
|
} |
||||||
|
|
||||||
|
@type params :: %{ |
||||||
|
proposed_by_validator_index: Zilliqa.validator_index(), |
||||||
|
block_hash: EthereumJSONRPC.hash(), |
||||||
|
view: non_neg_integer(), |
||||||
|
signature: EthereumJSONRPC.hash(), |
||||||
|
signers: Zilliqa.signers() |
||||||
|
} |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Decodes the JSON object returned by JSONRPC node into the `t:t/0` format. |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
iex> aqc_json = %{ |
||||||
|
...> "cosigned" => "[0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", |
||||||
|
...> "quorum_certificates" => [ |
||||||
|
...> %{ |
||||||
|
...> "block_hash" => "0x4b8939a7fb0d7de4b288bafd4d5caa02f53abf3c1e348fca5038eebbf68248fa", |
||||||
|
...> "cosigned" => "[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", |
||||||
|
...> "signature" => "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> "view" => "0x115cc7" |
||||||
|
...> }, |
||||||
|
...> %{ |
||||||
|
...> "block_hash" => "0x4b8939a7fb0d7de4b288bafd4d5caa02f53abf3c1e348fca5038eebbf68248fa", |
||||||
|
...> "cosigned" => "[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", |
||||||
|
...> "signature" => "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> "view" => "0x115cc7" |
||||||
|
...> }, |
||||||
|
...> %{ |
||||||
|
...> "block_hash" => "0x4b8939a7fb0d7de4b288bafd4d5caa02f53abf3c1e348fca5038eebbf68248fa", |
||||||
|
...> "cosigned" => "[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", |
||||||
|
...> "signature" => "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> "view" => "0x115cc7" |
||||||
|
...> }, |
||||||
|
...> %{ |
||||||
|
...> "block_hash" => "0x4b8939a7fb0d7de4b288bafd4d5caa02f53abf3c1e348fca5038eebbf68248fa", |
||||||
|
...> "cosigned" => "[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", |
||||||
|
...> "signature" => "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> "view" => "0x115cc7" |
||||||
|
...> } |
||||||
|
...> ], |
||||||
|
...> "signature" => "0x820f591cd78b29a69ba25bc85c4327fa3b0adb61a73a4f0bd943b4ab0b97e061eae9ac032d19fbfab7efb89fac2454ab0b89fea83185c0dac749ff55b0e2c21535a2b712872491577728db868d11939461a6bfde0d94d238f46b643bbe19767e", |
||||||
|
...> "view" => "0x115cca" |
||||||
|
...> } |
||||||
|
iex> quorum_certificates = aqc_json["quorum_certificates"] |
||||||
|
iex> bit_vector = aqc_json["cosigned"] |
||||||
|
iex> block_hash = "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d" |
||||||
|
iex> EthereumJSONRPC.Zilliqa.NestedQuorumCertificates.new(quorum_certificates, bit_vector, block_hash) |
||||||
|
%EthereumJSONRPC.Zilliqa.NestedQuorumCertificates{ |
||||||
|
signers: [1, 2, 3, 8], |
||||||
|
items: [ |
||||||
|
%EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
signers: [0, 1, 3, 8] |
||||||
|
}, |
||||||
|
%EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
signers: [0, 1, 3, 8] |
||||||
|
}, |
||||||
|
%EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
signers: [0, 1, 3, 8] |
||||||
|
}, |
||||||
|
%EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
signers: [0, 1, 3, 8] |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
""" |
||||||
|
@spec new([QuorumCertificate.elixir()], Zilliqa.bit_vector(), EthereumJSONRPC.hash()) :: t() |
||||||
|
def new(quorum_certificates, bit_vector, block_hash) do |
||||||
|
signers = bit_vector_to_signers(bit_vector) |
||||||
|
items = Enum.map(quorum_certificates, &QuorumCertificate.new(&1, block_hash)) |
||||||
|
|
||||||
|
%__MODULE__{ |
||||||
|
signers: signers, |
||||||
|
items: items |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Converts `t:t/0` format to params used in `Explorer.Chain`. |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
iex> nested_quorum_certificates = %EthereumJSONRPC.Zilliqa.NestedQuorumCertificates{ |
||||||
|
...> signers: [1, 2, 3, 8], |
||||||
|
...> items: [ |
||||||
|
...> %EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
...> block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
...> view: 1137863, |
||||||
|
...> signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> signers: [0, 1, 3, 8] |
||||||
|
...> }, |
||||||
|
...> %EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
...> block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
...> view: 1137863, |
||||||
|
...> signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> signers: [0, 1, 3, 8] |
||||||
|
...> }, |
||||||
|
...> %EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
...> block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
...> view: 1137863, |
||||||
|
...> signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> signers: [0, 1, 3, 8] |
||||||
|
...> }, |
||||||
|
...> %EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
...> block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
...> view: 1137863, |
||||||
|
...> signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> signers: [0, 1, 3, 8] |
||||||
|
...> } |
||||||
|
...> ] |
||||||
|
...> } |
||||||
|
iex> EthereumJSONRPC.Zilliqa.NestedQuorumCertificates.to_params(nested_quorum_certificates) |
||||||
|
[ |
||||||
|
%{ |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signers: [0, 1, 3, 8], |
||||||
|
proposed_by_validator_index: 1 |
||||||
|
}, |
||||||
|
%{ |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signers: [0, 1, 3, 8], |
||||||
|
proposed_by_validator_index: 2 |
||||||
|
}, |
||||||
|
%{ |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signers: [0, 1, 3, 8], |
||||||
|
proposed_by_validator_index: 3 |
||||||
|
}, |
||||||
|
%{ |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signers: [0, 1, 3, 8], |
||||||
|
proposed_by_validator_index: 8 |
||||||
|
} |
||||||
|
] |
||||||
|
""" |
||||||
|
@spec to_params(t()) :: [params()] |
||||||
|
def to_params(%__MODULE__{signers: signers, items: items}) do |
||||||
|
signers |
||||||
|
|> Enum.zip(items) |
||||||
|
|> Enum.map(fn {validator_index, cert} -> |
||||||
|
cert |
||||||
|
|> QuorumCertificate.to_params() |
||||||
|
|> Map.put(:proposed_by_validator_index, validator_index) |
||||||
|
end) |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,100 @@ |
|||||||
|
defmodule EthereumJSONRPC.Zilliqa.QuorumCertificate do |
||||||
|
@moduledoc """ |
||||||
|
Represents a quorum certificate associated with the block. |
||||||
|
""" |
||||||
|
import EthereumJSONRPC, only: [quantity_to_integer: 1] |
||||||
|
|
||||||
|
import EthereumJSONRPC.Zilliqa.Helper, |
||||||
|
only: [bit_vector_to_signers: 1] |
||||||
|
|
||||||
|
@type elixir :: %{ |
||||||
|
String.t() => EthereumJSONRPC.quantity() | EthereumJSONRPC.Zilliqa.bit_vector() | EthereumJSONRPC.hash() |
||||||
|
} |
||||||
|
|
||||||
|
@type t :: %__MODULE__{ |
||||||
|
block_hash: EthereumJSONRPC.hash(), |
||||||
|
view: non_neg_integer(), |
||||||
|
signature: EthereumJSONRPC.hash(), |
||||||
|
signers: [non_neg_integer()] |
||||||
|
} |
||||||
|
|
||||||
|
@type params :: %{ |
||||||
|
block_hash: EthereumJSONRPC.hash(), |
||||||
|
view: non_neg_integer(), |
||||||
|
signature: EthereumJSONRPC.hash(), |
||||||
|
signers: [non_neg_integer()] |
||||||
|
} |
||||||
|
|
||||||
|
defstruct [:block_hash, :view, :signature, :signers] |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Decodes the JSON object returned by JSONRPC node into the `t:t/0` format. |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
iex> qc_json = %{ |
||||||
|
...> "block_hash" => "0x4b8939a7fb0d7de4b288bafd4d5caa02f53abf3c1e348fca5038eebbf68248fa", |
||||||
|
...> "cosigned" => "[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", |
||||||
|
...> "signature" => "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> "view" => "0x115cc7" |
||||||
|
...> } |
||||||
|
iex> block_hash = "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d" |
||||||
|
iex> EthereumJSONRPC.Zilliqa.QuorumCertificate.new(qc_json, block_hash) |
||||||
|
%EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
signers: [0, 1, 3, 8] |
||||||
|
} |
||||||
|
""" |
||||||
|
@spec new(elixir(), EthereumJSONRPC.hash()) :: t() |
||||||
|
def new( |
||||||
|
%{ |
||||||
|
"view" => view, |
||||||
|
"cosigned" => bit_vector, |
||||||
|
"signature" => signature |
||||||
|
}, |
||||||
|
block_hash |
||||||
|
) do |
||||||
|
%__MODULE__{ |
||||||
|
block_hash: block_hash, |
||||||
|
view: quantity_to_integer(view), |
||||||
|
signature: signature, |
||||||
|
signers: bit_vector_to_signers(bit_vector) |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Converts `t:t/0` format to params used in `Explorer.Chain`. |
||||||
|
|
||||||
|
## Examples |
||||||
|
|
||||||
|
iex> qc = %EthereumJSONRPC.Zilliqa.QuorumCertificate{ |
||||||
|
...> block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
...> view: 1137863, |
||||||
|
...> signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
...> signers: [0, 1, 3, 8] |
||||||
|
...> } |
||||||
|
iex> EthereumJSONRPC.Zilliqa.QuorumCertificate.to_params(qc) |
||||||
|
%{ |
||||||
|
block_hash: "0x9c8a047e40ea975cb14c5ccff232a2210fbf5d77b10c748b3559ada0d4adad9d", |
||||||
|
view: 1137863, |
||||||
|
signature: "0xa78c7f3e07e1df963ddeda17a1e5afd97c7c8a6fc8e0616249c22a2a1cc91f8eef6073cab8ba22b50cc7b38090f1ad9109473d30f24d57858d1f28c6679b3c4deeb800e5572b5e15604596594d506d3103a44d8b707da581f1a4b82310aeecb6", |
||||||
|
signers: [0, 1, 3, 8] |
||||||
|
} |
||||||
|
""" |
||||||
|
@spec to_params(t()) :: params() |
||||||
|
def to_params(%__MODULE__{ |
||||||
|
block_hash: block_hash, |
||||||
|
view: view, |
||||||
|
signature: signature, |
||||||
|
signers: signers |
||||||
|
}) do |
||||||
|
%{ |
||||||
|
block_hash: block_hash, |
||||||
|
view: view, |
||||||
|
signature: signature, |
||||||
|
signers: signers |
||||||
|
} |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,7 @@ |
|||||||
|
defmodule EthereumJSONRPC.ZilliqaTest do |
||||||
|
use ExUnit.Case, async: true |
||||||
|
|
||||||
|
doctest EthereumJSONRPC.Zilliqa.AggregateQuorumCertificate |
||||||
|
doctest EthereumJSONRPC.Zilliqa.NestedQuorumCertificates |
||||||
|
doctest EthereumJSONRPC.Zilliqa.QuorumCertificate |
||||||
|
end |
@ -0,0 +1,79 @@ |
|||||||
|
defmodule Explorer.Chain.Import.Runner.Zilliqa.AggregateQuorumCertificates do |
||||||
|
@moduledoc """ |
||||||
|
Bulk imports `t:Explorer.Chain.Zilliqa.AggregateQuorumCertificate.t/0`. |
||||||
|
""" |
||||||
|
|
||||||
|
require Ecto.Query |
||||||
|
|
||||||
|
alias Ecto.{Changeset, Multi, Repo} |
||||||
|
alias Explorer.Chain.Import |
||||||
|
alias Explorer.Chain.Zilliqa.AggregateQuorumCertificate |
||||||
|
alias Explorer.Prometheus.Instrumenter |
||||||
|
|
||||||
|
@behaviour Import.Runner |
||||||
|
|
||||||
|
# milliseconds |
||||||
|
@timeout 60_000 |
||||||
|
|
||||||
|
@type imported :: [AggregateQuorumCertificate.t()] |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
def ecto_schema_module, do: AggregateQuorumCertificate |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
def option_key, do: :zilliqa_aggregate_quorum_certificates |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
@spec imported_table_row() :: %{:value_description => binary(), :value_type => binary()} |
||||||
|
def imported_table_row do |
||||||
|
%{ |
||||||
|
value_type: "[#{ecto_schema_module()}.t()]", |
||||||
|
value_description: "List of `t:#{ecto_schema_module()}.t/0`s" |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
@spec run(Multi.t(), list(), map()) :: Multi.t() |
||||||
|
def run(multi, changes_list, %{timestamps: timestamps} = options) do |
||||||
|
insert_options = |
||||||
|
options |
||||||
|
|> Map.get(option_key(), %{}) |
||||||
|
|> Map.take(~w(on_conflict timeout)a) |
||||||
|
|> Map.put_new(:timeout, @timeout) |
||||||
|
|> Map.put(:timestamps, timestamps) |
||||||
|
|
||||||
|
Multi.run(multi, :insert_zilliqa_aggregate_quorum_certificates, fn repo, _ -> |
||||||
|
Instrumenter.block_import_stage_runner( |
||||||
|
fn -> insert(repo, changes_list, insert_options) end, |
||||||
|
:block_referencing, |
||||||
|
:zilliqa_aggregate_quorum_certificates, |
||||||
|
:zilliqa_aggregate_quorum_certificates |
||||||
|
) |
||||||
|
end) |
||||||
|
end |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
def timeout, do: @timeout |
||||||
|
|
||||||
|
@spec insert(Repo.t(), [map()], %{required(:timeout) => timeout(), required(:timestamps) => Import.timestamps()}) :: |
||||||
|
{:ok, [AggregateQuorumCertificate.t()]} |
||||||
|
| {:error, [Changeset.t()]} |
||||||
|
def insert(repo, changes_list, %{timeout: timeout, timestamps: timestamps} = _options) when is_list(changes_list) do |
||||||
|
# Enforce Zilliqa.AggregateQuorumCertificate ShareLocks order (see docs: sharelock.md) |
||||||
|
ordered_changes_list = Enum.sort_by(changes_list, & &1.block_hash) |
||||||
|
|
||||||
|
{:ok, inserted} = |
||||||
|
Import.insert_changes_list( |
||||||
|
repo, |
||||||
|
ordered_changes_list, |
||||||
|
for: AggregateQuorumCertificate, |
||||||
|
returning: true, |
||||||
|
timeout: timeout, |
||||||
|
timestamps: timestamps, |
||||||
|
conflict_target: :block_hash, |
||||||
|
on_conflict: :nothing |
||||||
|
) |
||||||
|
|
||||||
|
{:ok, inserted} |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,86 @@ |
|||||||
|
defmodule Explorer.Chain.Import.Runner.Zilliqa.NestedQuorumCertificates do |
||||||
|
@moduledoc """ |
||||||
|
Bulk imports `t:Explorer.Chain.Zilliqa.NestedQuorumCertificate.t/0`. |
||||||
|
""" |
||||||
|
|
||||||
|
require Ecto.Query |
||||||
|
|
||||||
|
alias Ecto.{Changeset, Multi, Repo} |
||||||
|
alias Explorer.Chain.Import |
||||||
|
alias Explorer.Chain.Zilliqa.NestedQuorumCertificate |
||||||
|
alias Explorer.Prometheus.Instrumenter |
||||||
|
|
||||||
|
@behaviour Import.Runner |
||||||
|
|
||||||
|
# milliseconds |
||||||
|
@timeout 60_000 |
||||||
|
|
||||||
|
@type imported :: [NestedQuorumCertificate.t()] |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
def ecto_schema_module, do: NestedQuorumCertificate |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
def option_key, do: :zilliqa_nested_quorum_certificates |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
@spec imported_table_row() :: %{:value_description => binary(), :value_type => binary()} |
||||||
|
def imported_table_row do |
||||||
|
%{ |
||||||
|
value_type: "[#{ecto_schema_module()}.t()]", |
||||||
|
value_description: "List of `t:#{ecto_schema_module()}.t/0`s" |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
@spec run(Multi.t(), list(), map()) :: Multi.t() |
||||||
|
def run(multi, changes_list, %{timestamps: timestamps} = options) do |
||||||
|
insert_options = |
||||||
|
options |
||||||
|
|> Map.get(option_key(), %{}) |
||||||
|
|> Map.take(~w(on_conflict timeout)a) |
||||||
|
|> Map.put_new(:timeout, @timeout) |
||||||
|
|> Map.put(:timestamps, timestamps) |
||||||
|
|
||||||
|
Multi.run(multi, :insert_zilliqa_nested_quorum_certificates, fn repo, _ -> |
||||||
|
Instrumenter.block_import_stage_runner( |
||||||
|
fn -> insert(repo, changes_list, insert_options) end, |
||||||
|
:block_referencing, |
||||||
|
:zilliqa_nested_quorum_certificates, |
||||||
|
:zilliqa_nested_quorum_certificates |
||||||
|
) |
||||||
|
end) |
||||||
|
end |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
def timeout, do: @timeout |
||||||
|
|
||||||
|
@spec insert(Repo.t(), [map()], %{required(:timeout) => timeout(), required(:timestamps) => Import.timestamps()}) :: |
||||||
|
{:ok, [NestedQuorumCertificate.t()]} |
||||||
|
| {:error, [Changeset.t()]} |
||||||
|
def insert(repo, changes_list, %{timeout: timeout, timestamps: timestamps} = _options) when is_list(changes_list) do |
||||||
|
# Enforce Zilliqa.NestedQuorumCertificate ShareLocks order (see docs: sharelock.md) |
||||||
|
ordered_changes_list = |
||||||
|
Enum.sort_by( |
||||||
|
changes_list, |
||||||
|
&{&1.block_hash, &1.proposed_by_validator_index} |
||||||
|
) |
||||||
|
|
||||||
|
{:ok, inserted} = |
||||||
|
Import.insert_changes_list( |
||||||
|
repo, |
||||||
|
ordered_changes_list, |
||||||
|
for: NestedQuorumCertificate, |
||||||
|
returning: true, |
||||||
|
timeout: timeout, |
||||||
|
timestamps: timestamps, |
||||||
|
conflict_target: [ |
||||||
|
:block_hash, |
||||||
|
:proposed_by_validator_index |
||||||
|
], |
||||||
|
on_conflict: :nothing |
||||||
|
) |
||||||
|
|
||||||
|
{:ok, inserted} |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,79 @@ |
|||||||
|
defmodule Explorer.Chain.Import.Runner.Zilliqa.QuorumCertificates do |
||||||
|
@moduledoc """ |
||||||
|
Bulk imports `t:Explorer.Chain.Zilliqa.QuorumCertificate.t/0`. |
||||||
|
""" |
||||||
|
|
||||||
|
require Ecto.Query |
||||||
|
|
||||||
|
alias Ecto.{Changeset, Multi, Repo} |
||||||
|
alias Explorer.Chain.Import |
||||||
|
alias Explorer.Chain.Zilliqa.QuorumCertificate |
||||||
|
alias Explorer.Prometheus.Instrumenter |
||||||
|
|
||||||
|
@behaviour Import.Runner |
||||||
|
|
||||||
|
# milliseconds |
||||||
|
@timeout 60_000 |
||||||
|
|
||||||
|
@type imported :: [QuorumCertificate.t()] |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
def ecto_schema_module, do: QuorumCertificate |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
def option_key, do: :zilliqa_quorum_certificates |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
@spec imported_table_row() :: %{:value_description => binary(), :value_type => binary()} |
||||||
|
def imported_table_row do |
||||||
|
%{ |
||||||
|
value_type: "[#{ecto_schema_module()}.t()]", |
||||||
|
value_description: "List of `t:#{ecto_schema_module()}.t/0`s" |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
@spec run(Multi.t(), list(), map()) :: Multi.t() |
||||||
|
def run(multi, changes_list, %{timestamps: timestamps} = options) do |
||||||
|
insert_options = |
||||||
|
options |
||||||
|
|> Map.get(option_key(), %{}) |
||||||
|
|> Map.take(~w(on_conflict timeout)a) |
||||||
|
|> Map.put_new(:timeout, @timeout) |
||||||
|
|> Map.put(:timestamps, timestamps) |
||||||
|
|
||||||
|
Multi.run(multi, :insert_zilliqa_quorum_certificates, fn repo, _ -> |
||||||
|
Instrumenter.block_import_stage_runner( |
||||||
|
fn -> insert(repo, changes_list, insert_options) end, |
||||||
|
:block_referencing, |
||||||
|
:zilliqa_quorum_certificates, |
||||||
|
:zilliqa_quorum_certificates |
||||||
|
) |
||||||
|
end) |
||||||
|
end |
||||||
|
|
||||||
|
@impl Import.Runner |
||||||
|
def timeout, do: @timeout |
||||||
|
|
||||||
|
@spec insert(Repo.t(), [map()], %{required(:timeout) => timeout(), required(:timestamps) => Import.timestamps()}) :: |
||||||
|
{:ok, [QuorumCertificate.t()]} |
||||||
|
| {:error, [Changeset.t()]} |
||||||
|
def insert(repo, changes_list, %{timeout: timeout, timestamps: timestamps} = _options) when is_list(changes_list) do |
||||||
|
# Enforce Zilliqa.QuorumCertificate ShareLocks order (see docs: sharelock.md) |
||||||
|
ordered_changes_list = Enum.sort_by(changes_list, & &1.block_hash) |
||||||
|
|
||||||
|
{:ok, inserted} = |
||||||
|
Import.insert_changes_list( |
||||||
|
repo, |
||||||
|
ordered_changes_list, |
||||||
|
for: QuorumCertificate, |
||||||
|
returning: true, |
||||||
|
timeout: timeout, |
||||||
|
timestamps: timestamps, |
||||||
|
conflict_target: :block_hash, |
||||||
|
on_conflict: :nothing |
||||||
|
) |
||||||
|
|
||||||
|
{:ok, inserted} |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,64 @@ |
|||||||
|
defmodule Explorer.Chain.Zilliqa.AggregateQuorumCertificate do |
||||||
|
@moduledoc """ |
||||||
|
A stored representation of a Zilliqa aggregate quorum certificate in the |
||||||
|
context of PBFT consensus. |
||||||
|
|
||||||
|
In PBFT (Practical Byzantine Fault Tolerance) consensus, an aggregate quorum |
||||||
|
certificate combines multiple quorum certificates into one, providing proof |
||||||
|
that a block has been approved across multiple consensus rounds or by multiple |
||||||
|
subsets of validators. It includes aggregated signatures and references to |
||||||
|
nested quorum certificates. |
||||||
|
|
||||||
|
Changes in the schema should be reflected in the bulk import module: |
||||||
|
- `Explorer.Chain.Import.Runner.Zilliqa.AggregateQuorumCertificate` |
||||||
|
""" |
||||||
|
use Explorer.Schema |
||||||
|
|
||||||
|
alias Explorer.Chain.{Block, Hash} |
||||||
|
alias Explorer.Chain.Zilliqa.Hash.Signature, as: SignatureHash |
||||||
|
alias Explorer.Chain.Zilliqa.NestedQuorumCertificate |
||||||
|
|
||||||
|
@required_attrs ~w(block_hash view signature)a |
||||||
|
|
||||||
|
@typedoc """ |
||||||
|
* `view` - the view number associated with the quorum certificate, indicating |
||||||
|
the consensus round. |
||||||
|
* `signature` - the aggregated BLS (Boneh–Lynn–Shacham) signature representing |
||||||
|
the validators' agreement. |
||||||
|
* `block_hash` - the hash of the block associated with this aggregate quorum |
||||||
|
certificate. |
||||||
|
* `nested_quorum_certificates` - the list of nested quorum certificates that |
||||||
|
are part of this aggregate. |
||||||
|
""" |
||||||
|
@primary_key false |
||||||
|
typed_schema "zilliqa_aggregate_quorum_certificates" do |
||||||
|
field(:view, :integer) |
||||||
|
field(:signature, SignatureHash) |
||||||
|
|
||||||
|
belongs_to(:block, Block, |
||||||
|
foreign_key: :block_hash, |
||||||
|
primary_key: true, |
||||||
|
references: :hash, |
||||||
|
type: Hash.Full, |
||||||
|
null: false |
||||||
|
) |
||||||
|
|
||||||
|
has_many( |
||||||
|
:nested_quorum_certificates, |
||||||
|
NestedQuorumCertificate, |
||||||
|
foreign_key: :block_hash, |
||||||
|
references: :block_hash |
||||||
|
) |
||||||
|
|
||||||
|
timestamps() |
||||||
|
end |
||||||
|
|
||||||
|
@spec changeset(Ecto.Schema.t(), map()) :: Ecto.Changeset.t() |
||||||
|
def changeset(%__MODULE__{} = cert, attrs) do |
||||||
|
cert |
||||||
|
|> cast(attrs, @required_attrs) |
||||||
|
|> validate_required(@required_attrs) |
||||||
|
|> foreign_key_constraint(:block_hash) |
||||||
|
|> unique_constraint(:block_hash, name: :aggregate_quorum_certificates_pkey) |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,60 @@ |
|||||||
|
defmodule Explorer.Chain.Zilliqa.Hash.Signature do |
||||||
|
@moduledoc """ |
||||||
|
A 96-byte BLS signature of the supermajority of the validators. |
||||||
|
""" |
||||||
|
|
||||||
|
alias Explorer.Chain.Hash |
||||||
|
|
||||||
|
use Ecto.Type |
||||||
|
@behaviour Hash |
||||||
|
|
||||||
|
@byte_count 96 |
||||||
|
|
||||||
|
@typedoc """ |
||||||
|
A #{@byte_count}-byte BLS signature hash of the |
||||||
|
`t:Explorer.Chain.Zilliqa.QuorumCertificate.t/0` or |
||||||
|
`t:Explorer.Chain.Zilliqa.AggregateQuorumCertificate.t/0` or |
||||||
|
`t:Explorer.Chain.Zilliqa.NestedQuorumCertificate.t/0`. |
||||||
|
""" |
||||||
|
@type t :: %Hash{byte_count: unquote(@byte_count), bytes: <<_::unquote(@byte_count * Hash.bits_per_byte())>>} |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Casts a term to a `t`. |
||||||
|
""" |
||||||
|
@impl Ecto.Type |
||||||
|
@spec cast(term()) :: {:ok, t()} | :error |
||||||
|
def cast(term) do |
||||||
|
Hash.cast(__MODULE__, term) |
||||||
|
end |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Dumps a `t` to a binary. |
||||||
|
""" |
||||||
|
@impl Ecto.Type |
||||||
|
@spec dump(term()) :: {:ok, binary} | :error |
||||||
|
def dump(term) do |
||||||
|
Hash.dump(__MODULE__, term) |
||||||
|
end |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Loads a binary to a `t`. |
||||||
|
""" |
||||||
|
@impl Ecto.Type |
||||||
|
@spec load(term()) :: {:ok, t()} | :error |
||||||
|
def load(term) do |
||||||
|
Hash.load(__MODULE__, term) |
||||||
|
end |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Returns the type of the `t`. |
||||||
|
""" |
||||||
|
@impl Ecto.Type |
||||||
|
@spec type() :: :binary |
||||||
|
def type, do: :binary |
||||||
|
|
||||||
|
@doc """ |
||||||
|
Returns the byte count of the `t`. |
||||||
|
""" |
||||||
|
@impl Hash |
||||||
|
def byte_count, do: @byte_count |
||||||
|
end |
@ -0,0 +1,64 @@ |
|||||||
|
defmodule Explorer.Chain.Zilliqa.NestedQuorumCertificate do |
||||||
|
@moduledoc """ |
||||||
|
A stored representation of a nested quorum certificate in Zilliqa's PBFT |
||||||
|
consensus. |
||||||
|
|
||||||
|
In Zilliqa's PBFT (Practical Byzantine Fault Tolerance) consensus, an |
||||||
|
aggregate quorum certificate may include multiple nested quorum certificates. |
||||||
|
Each nested quorum certificate represents a quorum certificate proposed by a |
||||||
|
specific validator and contains its own aggregated signatures and participant |
||||||
|
information. |
||||||
|
|
||||||
|
Changes in the schema should be reflected in the bulk import module: |
||||||
|
- `Explorer.Chain.Import.Runner.Zilliqa.AggregateQuorumCertificate` |
||||||
|
""" |
||||||
|
use Explorer.Schema |
||||||
|
|
||||||
|
alias Explorer.Chain.Hash |
||||||
|
alias Explorer.Chain.Zilliqa.AggregateQuorumCertificate |
||||||
|
alias Explorer.Chain.Zilliqa.Hash.Signature, as: SignatureHash |
||||||
|
|
||||||
|
@required_attrs ~w(block_hash proposed_by_validator_index view signature signers)a |
||||||
|
|
||||||
|
@typedoc """ |
||||||
|
* `proposed_by_validator_index` - the index of the validator who proposed this |
||||||
|
nested quorum certificate. |
||||||
|
* `view` - the view number associated with the quorum certificate, indicating |
||||||
|
the consensus round. |
||||||
|
* `signature` - the aggregated BLS (Boneh–Lynn–Shacham) signature representing |
||||||
|
the validators' agreement. |
||||||
|
* `signers` - the array of integers representing the indices of validators who |
||||||
|
participated in the quorum (as indicated by the `cosigned` bit vector). |
||||||
|
* `block_hash` - the hash of the block associated with the aggregate quorum |
||||||
|
certificate to which this nested quorum certificate belongs. |
||||||
|
""" |
||||||
|
@primary_key false |
||||||
|
typed_schema "zilliqa_nested_quorum_certificates" do |
||||||
|
field(:proposed_by_validator_index, :integer, primary_key: true) |
||||||
|
field(:view, :integer) |
||||||
|
field(:signature, SignatureHash) |
||||||
|
field(:signers, {:array, :integer}) |
||||||
|
|
||||||
|
belongs_to(:aggregate_quorum_certificate, AggregateQuorumCertificate, |
||||||
|
foreign_key: :block_hash, |
||||||
|
references: :block_hash, |
||||||
|
primary_key: true, |
||||||
|
type: Hash.Full, |
||||||
|
null: false |
||||||
|
) |
||||||
|
|
||||||
|
timestamps() |
||||||
|
end |
||||||
|
|
||||||
|
@spec changeset(Ecto.Schema.t(), map()) :: Ecto.Changeset.t() |
||||||
|
def changeset(%__MODULE__{} = cert, attrs) do |
||||||
|
cert |
||||||
|
|> cast(attrs, @required_attrs) |
||||||
|
|> validate_required(@required_attrs) |
||||||
|
|> foreign_key_constraint(:block_hash) |
||||||
|
|> unique_constraint( |
||||||
|
[:proposed_by_validator_index, :block_hash], |
||||||
|
name: :nested_quorum_certificates_pkey |
||||||
|
) |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,56 @@ |
|||||||
|
defmodule Explorer.Chain.Zilliqa.QuorumCertificate do |
||||||
|
@moduledoc """ |
||||||
|
A stored representation of a Zilliqa quorum certificate in the context of PBFT |
||||||
|
consensus. |
||||||
|
|
||||||
|
In PBFT (Practical Byzantine Fault Tolerance) consensus, a quorum certificate |
||||||
|
is a data structure that serves as proof that a block has been approved by a |
||||||
|
supermajority of validators. It includes aggregated signatures and a bitmap |
||||||
|
indicating which validators participated in the consensus. |
||||||
|
|
||||||
|
Changes in the schema should be reflected in the bulk import module: |
||||||
|
- `Explorer.Chain.Import.Runner.Zilliqa.AggregateQuorumCertificate` |
||||||
|
""" |
||||||
|
use Explorer.Schema |
||||||
|
|
||||||
|
alias Explorer.Chain.{Block, Hash} |
||||||
|
alias Explorer.Chain.Zilliqa.Hash.Signature, as: SignatureHash |
||||||
|
|
||||||
|
@required_attrs ~w(block_hash view signature signers)a |
||||||
|
|
||||||
|
@typedoc """ |
||||||
|
* `view` - the view number associated with the quorum certificate, indicating |
||||||
|
the consensus round. |
||||||
|
* `signature` - the aggregated BLS (Boneh–Lynn–Shacham) signature representing |
||||||
|
the validators' agreement. |
||||||
|
* `signers` - the array of integers representing the indices of validators who |
||||||
|
participated in the quorum (as indicated by the `cosigned` bit vector). |
||||||
|
* `block_hash` - the hash of the block associated with this quorum |
||||||
|
certificate. |
||||||
|
""" |
||||||
|
@primary_key false |
||||||
|
typed_schema "zilliqa_quorum_certificates" do |
||||||
|
field(:view, :integer) |
||||||
|
field(:signature, SignatureHash) |
||||||
|
field(:signers, {:array, :integer}) |
||||||
|
|
||||||
|
belongs_to(:block, Block, |
||||||
|
foreign_key: :block_hash, |
||||||
|
primary_key: true, |
||||||
|
references: :hash, |
||||||
|
type: Hash.Full, |
||||||
|
null: false |
||||||
|
) |
||||||
|
|
||||||
|
timestamps() |
||||||
|
end |
||||||
|
|
||||||
|
@spec changeset(Ecto.Schema.t(), map()) :: Ecto.Schema.t() |
||||||
|
def changeset(%__MODULE__{} = cert, attrs) do |
||||||
|
cert |
||||||
|
|> cast(attrs, @required_attrs) |
||||||
|
|> validate_required(@required_attrs) |
||||||
|
|> foreign_key_constraint(:block_hash) |
||||||
|
|> unique_constraint(:block_hash, name: :quorum_certificates_pkey) |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,20 @@ |
|||||||
|
defmodule Explorer.Repo.Zilliqa.Migrations.CreateQuorumCertificate do |
||||||
|
use Ecto.Migration |
||||||
|
|
||||||
|
def change do |
||||||
|
create table(:zilliqa_quorum_certificates, primary_key: false) do |
||||||
|
add( |
||||||
|
:block_hash, |
||||||
|
references(:blocks, column: :hash, type: :bytea, on_delete: :delete_all), |
||||||
|
null: false, |
||||||
|
primary_key: true |
||||||
|
) |
||||||
|
|
||||||
|
add(:view, :integer, null: false) |
||||||
|
add(:signature, :binary, null: false) |
||||||
|
add(:signers, {:array, :smallint}, null: false) |
||||||
|
|
||||||
|
timestamps() |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,19 @@ |
|||||||
|
defmodule Explorer.Repo.Zilliqa.Migrations.CreateAggregateQuorumCertificate do |
||||||
|
use Ecto.Migration |
||||||
|
|
||||||
|
def change do |
||||||
|
create table(:zilliqa_aggregate_quorum_certificates, primary_key: false) do |
||||||
|
add( |
||||||
|
:block_hash, |
||||||
|
references(:blocks, column: :hash, type: :bytea, on_delete: :delete_all), |
||||||
|
null: false, |
||||||
|
primary_key: true |
||||||
|
) |
||||||
|
|
||||||
|
add(:view, :integer, null: false) |
||||||
|
add(:signature, :binary, null: false) |
||||||
|
|
||||||
|
timestamps() |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,21 @@ |
|||||||
|
defmodule Explorer.Repo.Zilliqa.Migrations.CreateNestedQuorumCertificate do |
||||||
|
use Ecto.Migration |
||||||
|
|
||||||
|
def change do |
||||||
|
create table(:zilliqa_nested_quorum_certificates, primary_key: false) do |
||||||
|
add( |
||||||
|
:block_hash, |
||||||
|
references(:blocks, column: :hash, type: :bytea, on_delete: :delete_all), |
||||||
|
null: false, |
||||||
|
primary_key: true |
||||||
|
) |
||||||
|
|
||||||
|
add(:proposed_by_validator_index, :smallint, primary_key: true) |
||||||
|
add(:view, :integer, null: false) |
||||||
|
add(:signature, :binary, null: false) |
||||||
|
add(:signers, {:array, :smallint}, null: false) |
||||||
|
|
||||||
|
timestamps() |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,9 @@ |
|||||||
|
defmodule Explorer.Repo.Zilliqa.Migrations.AddViewToBlock do |
||||||
|
use Ecto.Migration |
||||||
|
|
||||||
|
def change do |
||||||
|
alter table(:blocks) do |
||||||
|
add(:zilliqa_view, :integer) |
||||||
|
end |
||||||
|
end |
||||||
|
end |
Loading…
Reference in new issue