Giter VIP home page Giter VIP logo

block-metrics's Introduction

Requires go1.11+

You must also export GO111MODULE=on in your environment to use the go modules feature.

Run locally

For local development you can use a local Postgres instance and any Tendermint node address.

# Run local Postgres instance
$ docker run -it --rm -e POSTGRES_HOST_AUTH_METHOD='trust' -p 5432:5432 postgres:alpine

# Run collector. Default configuration is expected to work for local
# development. If needed it can be changed via environment variables.
$ TENDERMINT_WS_URI="wss://rpc-private-a-vip-mainnet.iov.one/websocket" \
  POSTGRES_HOST="localhost" \
  POSTGRES_DB_NAME="postgres" \
  POSTGRES_USER="postgres" \
  POSTGRES_PASSWORD="" \
  POSTGRES_SSL_ENABLE="disable" \
  POSTGRES_PORT="5432" \
    go run cmd/collector/main.go

Sample queries

First run the above command to fill the database with all the sample hugnet data, then:

Find active validators at height h:

SELECT v.address 
    FROM validators v 
    INNER JOIN block_participations p ON v.id = p.validator_id 
    WHERE p.block_id = 57;

Find all missing precommits (over all validators and blocks)

SELECT * FROM block_participations WHERE validated = false;

SELECT b.block_height, b.proposer_id, p.validator_id, b.block_time 
    FROM block_participations p 
    INNER JOIN blocks b ON p.block_id = b.block_height 
    WHERE p.validated = false;

Find total counts for each validator:

SELECT COUNT(NULLIF(validated, false)) as signed, COUNT(NULLIF(validated, true)) as missed, validator_id 
    FROM block_participations 
    GROUP BY validator_id 
    ORDER BY validator_id;

SELECT v.address, COUNT(NULLIF(p.validated, false)) as signed, COUNT(NULLIF(p.validated, true)) as missed 
    FROM block_participations p 
    INNER JOIN validators v ON p.validator_id = v.id 
    GROUP BY v.address 
    ORDER BY v.address;

Find missed by block proposer:

(by validator id)

SELECT b.proposer_id, COUNT(*) 
    FROM blocks b 
    INNER JOIN block_participations p ON b.block_height = p.block_id 
    WHERE p.validated = false 
    GROUP BY b.proposer_id
    ORDER BY count DESC;

(or with full address)

SELECT v.address, COUNT(*) 
    FROM validators v 
    INNER JOIN blocks b ON b.proposer_id = v.id 
    INNER JOIN block_participations p ON b.block_height = p.block_id 
    WHERE p.validated = false 
    GROUP BY v.address
    ORDER BY count DESC;

Find misses by proposer and signer:

SELECT b.proposer_id, p.validator_id, COUNT(*) 
    FROM blocks b 
    INNER JOIN block_participations p ON b.block_height = p.block_id 
    WHERE p.validated = false 
    GROUP BY b.proposer_id, p.validator_id;

Find misses by next proposer and signer: (next proposer makes the canonical commits, and note how this ensures no more self-censorship)

SELECT b.proposer_id, p.validator_id, COUNT(*) 
    FROM blocks b 
    INNER JOIN block_participations p ON b.block_height = p.block_id + 1
    WHERE p.validated = false 
    GROUP BY b.proposer_id, p.validator_id;

block-metrics's People

Contributors

davepuchyr avatar ethanfrey avatar husio avatar orkunkl avatar ruseinov avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

block-metrics's Issues

Begin Block Metrics Collector with counts

Is your feature request related to a problem? Please describe.
This is a refined first step to https://github.com/iov-one/weave/issues/427

Describe the solution you'd like

Let us make a simple infrastructure to collect basic info. This should be a go binary that runs with a few cli flags or environmental variables to configure it. (Ideally just needs two urls). This binary should be in an open-source repo outside of weave. Make a new one, or reuse an existing one.

This collector should connect to (1) a postgresql db and (2) a tendermint node rpc server. On connection to (1), it should check if there is the given schema and run a migration if needed. If there is some data, it should check the most recent block imported and begin after that.

For (2), it should query historical blocks starting with first block not stored in the database, and continue until it has caught up with the blockchain. At that point it should move to subscribe mode and use a block header subscription to update immediately for every block.

Data to store:

  • Header summary: block height, block hash, timestamp, proposer id (reference a validator). Height could be primary id if we only store one chain per db.
  • List of validators. store (id, public key, memo). We can lookup by public key here, but use the id in all other tables (rather than 64 char text) as a key to join on. Every new validator we see on a block should be added here by the collector. Memos would only be added manually by a DBA.
  • calculate active (if they are in the present validator set, validator hash in header, full list via rpc), bu storing a table with (start, end) blocks for each validator, when it was in the validator set. A validator my leave and come back later, so this may be contain multiple entries for validator. Provide an sql query to list all actives validators at a given height, and another for total number of blocks a given validator was active on.
  • Maintain a (short) table: signed blocks, with one entry per validator, containing a count of the number of blocks they signed.
  • Maintain a (longer) table: missed blocks, with one entry for every missed signature. Contains (blockheight, validator id). We can get total missed blocks for a validator here, and use inner joins to begin to find correlations.

Storing this data will resolve this story. The only queries that must be defined (provide sql that can be executed on psql) are:

  • List active validators at height h
  • List who missed block h
  • List total signed blocks, total active blocks for every validator

Display validator name instead of id

Please use the following mappings to display the validator name, rather than id, in the explorer:

61B819A0BCF4E65AF8B6ED3AB287935074B8C7E3 Cosmostation
3B4F5C11663DC10A6D32403F945DED42AE1DD362 StakeWith.Us
8411B44F2FF2CE6A3143121EB5EEC1A23FCF2631 HashQuark
058078082E8ED2431EA61E69657BE27F0D7456FA Node A Team
4A6CDCD260D1527CD1F89ECB5BA3A160FAB3B5F7 Forbole
A811EB8C0E76991BA241278886625CF081EFF874 01node.com
4C74A4E2156493E5FB329BE619C188519629CCE3 Bianjie
28BFE674AF17CFE4736C979CECFFC03A5490DE96 ChainLayer
DF97841F98E18B02F670C62830E13C40FFCE9D1E syncnode
A5F88A83C831E6D84C83EED33870F4015D0FE94A Stake Capital

The validator set will not change for months so feel free to not be clever with the implementation, ie hard-code the values if you wish.

Websocket disconnect issue

After running the sync on hugnet for a while, the metrics reporter died:

$ TENDERMINT_WS_URI="wss://bns.hugnet.iov.one/websocket"   POSTGRES_URI="postgresql://postgres@localhost:5432"     go run cmd/collector/main.go

2019/04/01 19:00:37 cannot unmarshal JSONRPC message: read tcp 192.168.1.39:58936->34.76.6.53:443: use of closed network connection
sync: blocks for 11444: query tendermint: -32603: Internal error: failed response
exit status 2

Maybe you need to add the ping-pong websocket keep-alive protocol?

Validate the correctness of the data

I just synced with hugnet to find some missed blocks, and got the following:

postgres=# select block_height, proposer_id, participant_ids from blocks where array_length(participant_ids, 1) != 4;
 block_height | proposer_id | participant_ids 
--------------+-------------+-----------------
            5 |           2 | {1,3,4}
           10 |           1 | {1,3,4}
           12 |           4 | {2,1,4}
           69 |           2 | {1,3,4}
        11443 |           3 | {1,3,4}
(5 rows)

Note that in 2 of the 5 examples, the proposer was not in the list of participants. Maybe there is some mis-match, like those participants are those who signed the block before or after??

Fix README

I updated to go1.11.5 just to run this, and got...

TENDERMINT_RPC="ws://bnsd.hugnet.iov.one" go run cmd/collector/main.go

pkg/metrics/tendermint.go:12:2: cannot find package "github.com/gorilla/websocket" in any of:
        /usr/lib/go-1.11/src/github.com/gorilla/websocket (from $GOROOT)
        /home/ethan/go/src/github.com/gorilla/websocket (from $GOPATH)
pkg/metrics/pq.go:9:2: cannot find package "github.com/lib/pq" in any of:
        /usr/lib/go-1.11/src/github.com/lib/pq (from $GOROOT)
        /home/ethan/go/src/github.com/lib/pq (from $GOPATH)

And the cli args are just wrong

Define and build block metrics -> db collector

TODO: evaluate state after we finish #1 (and merge #11) to see what is left to do

We need to grab block header info along with which validators signed into a postgresql database. (or other to be determined).

Should allow non-devs (BI?) to write queries to detect downtime (not just total, but also how long at once), also detect censorship attacks (validator A vote never includes when B is proposed), etc....

Connects to tendermint rpc to get this info and runs as a daemon to fill in this database.

Fix source and destination in JSON to normal IOV address

Current implementation saves source and the destination of send tx as

{"path":"cash/send","details":"{\"metadata\":{\"schema\":1},\"source\":\"C1888F21C55E9EF00B0220C7CAECBE862C4591F0\",\"destination\":\"FABE94B2D4CF2A7513888F501BB92D7C10B63C74\",\"amount\":{\"fractional\":1,\"ticker\":\"IOV\"}}"}

We need to save addresses as bech32

Determine when a validator missed its opportunity to propose

A key aspect of the validator rewards hinges on knowing when a validator missed its opportunity to propose a block. Therefore, we need to ensure data that can be used to make the determination is recorded.

One possible means to determine a missed proposal opportunity is to observe proposer_priority. If, for a given validator, proposer_priority decreased but the validator was not the block proposer then it missed its opportunity to propose. consensus.create_empty_blocks=false might complicate things.

Please determine the best means to calculate a missed proposal opportunity and ensure that the required data is collected.

Enhance block-metrics so that a reverse name lookup can be performed

As a user, I want to know the accounts that are associated with a given target.

The relation between all targets and their associated accounts needs to be persisted in the database and kept up-to-date. Additionally, all certificates in an account need to be persisted so that an external call to the bnsapi is not required to obtain them.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.