Skip to content
This repository has been archived by the owner on Oct 18, 2023. It is now read-only.

Commit

Permalink
[bor] Implement bor_getSnapshotProposerSequence RPC method (erigontec…
Browse files Browse the repository at this point in the history
…h#7770)

Implements `bor_getSnapshotProposerSequence` RPC method which returns an
ordered set of validators (selected to mine) for a given block number.

```
> curl http://localhost:8545 -X POST --data '{"jsonrpc":"2.0","method":"bor_getSnapshotProposerSequence","params":["0x235A310"],"id":1}' -H "Content-Type: application/json"

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "Signers": [
      {
        "Signer": "0xcfef2a3dc244ef7d0fb93c45e762d671445c4569",
        "Difficulty": 5
      },
      {
        "Signer": "0x3a22c8bc68e98b0faf40f349dd2b2890fae01484",
        "Difficulty": 4
      },
      {
        "Signer": "0xbe188d6641e8b680743a4815dfa0f6208038960f",
        "Difficulty": 3
      },
      {
        "Signer": "0xc26880a0af2ea0c7e8130e6ec47af756465452e8",
        "Difficulty": 2
      },
      {
        "Signer": "0xc275dc8be39f50d12f66b6a63629c39da5bae5bd",
        "Difficulty": 1
      }
    ],
    "Diff": 5,
    "Author": "0xcfef2a3dc244ef7d0fb93c45e762d671445c4569"
  }
}
```
  • Loading branch information
manav2401 authored Jun 27, 2023
1 parent a2dd5da commit 6f0a02a
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 0 deletions.
1 change: 1 addition & 0 deletions cmd/rpcdaemon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ The following table shows the current implementation status of Erigon's RPC daem
| bor_getSignersAtHash | Yes | Bor only |
| bor_getCurrentProposer | Yes | Bor only |
| bor_getCurrentValidators | Yes | Bor only |
| bor_getSnapshotProposerSequence | Yes | Bor only |
| bor_getRootHash | Yes | Bor only |

### GraphQL
Expand Down
1 change: 1 addition & 0 deletions cmd/rpcdaemon/commands/bor_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type BorAPI interface {
GetSignersAtHash(hash common.Hash) ([]common.Address, error)
GetCurrentProposer() (common.Address, error)
GetCurrentValidators() ([]*valset.Validator, error)
GetSnapshotProposerSequence(blockNrOrHash *rpc.BlockNumberOrHash) (BlockSigners, error)
GetRootHash(start uint64, end uint64) (string, error)
}

Expand Down
14 changes: 14 additions & 0 deletions cmd/rpcdaemon/commands/bor_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"errors"
"fmt"
"sort"

"github.com/ledgerwatch/erigon-lib/chain"
"github.com/ledgerwatch/erigon-lib/common"
Expand Down Expand Up @@ -160,3 +161,16 @@ func author(api *BorImpl, tx kv.Tx, header *types.Header) (common.Address, error
config, _ := api.chainConfig(tx)
return ecrecover(header, config.Bor)
}

func rankMapDifficulties(values map[common.Address]uint64) []difficultiesKV {
ss := make([]difficultiesKV, 0, len(values))
for k, v := range values {
ss = append(ss, difficultiesKV{k, v})
}

sort.Slice(ss, func(i, j int) bool {
return ss[i].Difficulty > ss[j].Difficulty
})

return ss
}
92 changes: 92 additions & 0 deletions cmd/rpcdaemon/commands/bor_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,98 @@ func (api *BorImpl) GetCurrentValidators() ([]*valset.Validator, error) {
return snap.ValidatorSet.Validators, nil
}

type BlockSigners struct {
Signers []difficultiesKV
Diff int
Author common.Address
}

type difficultiesKV struct {
Signer common.Address
Difficulty uint64
}

func (api *BorImpl) GetSnapshotProposerSequence(blockNrOrHash *rpc.BlockNumberOrHash) (BlockSigners, error) {
// init chain db
ctx := context.Background()
tx, err := api.db.BeginRo(ctx)
if err != nil {
return BlockSigners{}, err
}
defer tx.Rollback()

// Retrieve the requested block number (or current if none requested)
var header *types.Header
if blockNrOrHash == nil {
header = rawdb.ReadCurrentHeader(tx)
} else {
if blockNr, ok := blockNrOrHash.Number(); ok {
if blockNr == rpc.LatestBlockNumber {
header = rawdb.ReadCurrentHeader(tx)
} else {
header, err = getHeaderByNumber(ctx, blockNr, api, tx)
}
} else {
if blockHash, ok := blockNrOrHash.Hash(); ok {
header, err = getHeaderByHash(ctx, api, tx, blockHash)
}
}
}

// Ensure we have an actually valid block
if header == nil || err != nil {
return BlockSigners{}, errUnknownBlock
}

// init consensus db
borTx, err := api.borDb.BeginRo(ctx)
if err != nil {
return BlockSigners{}, err
}
defer borTx.Rollback()

parent, err := getHeaderByNumber(ctx, rpc.BlockNumber(int64(header.Number.Uint64()-1)), api, tx)
if parent == nil || err != nil {
return BlockSigners{}, errUnknownBlock
}
snap, err := snapshot(ctx, api, tx, borTx, parent)

var difficulties = make(map[common.Address]uint64)

if err != nil {
return BlockSigners{}, err
}

proposer := snap.ValidatorSet.GetProposer().Address
proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer)

signers := snap.signers()
for i := 0; i < len(signers); i++ {
tempIndex := i
if tempIndex < proposerIndex {
tempIndex = tempIndex + len(signers)
}

difficulties[signers[i]] = uint64(len(signers) - (tempIndex - proposerIndex))
}

rankedDifficulties := rankMapDifficulties(difficulties)

author, err := author(api, tx, header)
if err != nil {
return BlockSigners{}, err
}

diff := int(difficulties[author])
blockSigners := BlockSigners{
Signers: rankedDifficulties,
Diff: diff,
Author: author,
}

return blockSigners, nil
}

// GetRootHash returns the merkle root of the start to end block headers
func (api *BorImpl) GetRootHash(start, end uint64) (string, error) {
length := end - start + 1
Expand Down

0 comments on commit 6f0a02a

Please sign in to comment.