Add ability to see this nodes public address (that is used for signing) (#856)

Add block sealing information to IBFT API .
This commit is contained in:
Peter Fox 2019-10-29 04:27:46 +00:00 committed by Samer Falah
parent 1dcee8518b
commit 66d91d0210
4 changed files with 155 additions and 15 deletions

View File

@ -29,6 +29,66 @@ type API struct {
istanbul *backend
}
// BlockSigners is contains who created and who signed a particular block, denoted by its number and hash
type BlockSigners struct {
Number uint64
Hash common.Hash
Author common.Address
Committers []common.Address
}
// NodeAddress returns the public address that is used to sign block headers in IBFT
func (api *API) NodeAddress() common.Address {
return api.istanbul.Address()
}
// GetSignersFromBlock returns the signers and minter for a given block number, or the
// latest block available if none is specified
func (api *API) GetSignersFromBlock(number *rpc.BlockNumber) (*BlockSigners, error) {
// Retrieve the requested block number (or current if none requested)
var header *types.Header
if number == nil || *number == rpc.LatestBlockNumber {
header = api.chain.CurrentHeader()
} else {
header = api.chain.GetHeaderByNumber(uint64(number.Int64()))
}
if header == nil {
return nil, errUnknownBlock
}
return api.signers(header)
}
// GetSignersFromBlockByHash returns the signers and minter for a given block hash
func (api *API) GetSignersFromBlockByHash(hash common.Hash) (*BlockSigners, error) {
header := api.chain.GetHeaderByHash(hash)
if header == nil {
return nil, errUnknownBlock
}
return api.signers(header)
}
func (api *API) signers(header *types.Header) (*BlockSigners, error) {
author, err := api.istanbul.Author(header)
if err != nil {
return nil, err
}
committers, err := api.istanbul.Signers(header)
if err != nil {
return nil, err
}
return &BlockSigners{
Number: header.Number.Uint64(),
Hash: header.Hash(),
Author: author,
Committers: committers,
}, nil
}
// GetSnapshot retrieves the state snapshot at a given block.
func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
// Retrieve the requested block number (or current if none requested)

View File

@ -103,6 +103,31 @@ func (sb *backend) Author(header *types.Header) (common.Address, error) {
return ecrecover(header)
}
// Signers extracts all the addresses who have signed the given header
// It will extract for each seal who signed it, regardless of if the seal is
// repeated
func (sb *backend) Signers(header *types.Header) ([]common.Address, error) {
extra, err := types.ExtractIstanbulExtra(header)
if err != nil {
return []common.Address{}, err
}
var addrs []common.Address
proposalSeal := istanbulCore.PrepareCommittedSeal(header.Hash())
// 1. Get committed seals from current header
for _, seal := range extra.CommittedSeal {
// 2. Get the original address by seal and parent block hash
addr, err := istanbul.GetSignatureAddress(proposalSeal, seal)
if err != nil {
sb.logger.Error("not a valid address", "err", err)
return nil, errInvalidSignature
}
addrs = append(addrs, addr)
}
return addrs, nil
}
// VerifyHeader checks whether a header conforms to the consensus rules of a
// given engine. Verifying the seal may be done optionally here, or explicitly
// via the VerifySeal method.
@ -271,22 +296,16 @@ func (sb *backend) verifyCommittedSeals(chain consensus.ChainReader, header *typ
validators := snap.ValSet.Copy()
// Check whether the committed seals are generated by parent's validators
validSeal := 0
proposalSeal := istanbulCore.PrepareCommittedSeal(header.Hash())
// 1. Get committed seals from current header
for _, seal := range extra.CommittedSeal {
// 2. Get the original address by seal and parent block hash
addr, err := istanbul.GetSignatureAddress(proposalSeal, seal)
if err != nil {
sb.logger.Error("not a valid address", "err", err)
return errInvalidSignature
}
// Every validator can have only one seal. If more than one seals are signed by a
// validator, the validator cannot be found and errInvalidCommittedSeals is returned.
committers, err := sb.Signers(header)
if err != nil {
return err
}
for _, addr := range committers {
if validators.RemoveValidator(addr) {
validSeal += 1
} else {
return errInvalidCommittedSeals
validSeal++
continue
}
return errInvalidCommittedSeals
}
// The length of validSeal should be larger than number of faulty node + 1

View File

@ -84,3 +84,48 @@ istanbul.propose(address, auth)
#### Parameters
`String` - The address of candidate
`bool` - `true` votes in and `false` votes out
### istanbul.nodeAddress
Retrieves the public address that is used to sign proposals, which is derived from the nodes `nodekey`.
```
istanbul.nodeAddress()
```
#### Returns
`string` - The nodes public signing address
### istanbul.getSignersFromBlock
Retrieves the public addresses for whose seals are included in the block. This means that they participated in the
consensus for this block and attested to its validity.
A block number may be optionally given, or else the current block is assumed.
```
istanbul.getSignersFromBlock(blockNumber)
```
#### Parameters
`Number` - The block number to retrieve
#### Returns
`Object` -
- `number`: `Number` - The retrieved block's number
- `hash`: `String` - The retrieved block's hash
- `author`: `String` - The address of the block proposer
- `committers`: `[]String` - The list of all addresses whose seal appears in this block
### istanbul.getSignersFromBlockByHash
Retrieves the public addresses for whose seals are included in the block. This means that they participated in the
consensus for this block and attested to its validity. A block hash must be given, and does NOT default to the current
latest block.
```
istanbul.getSignersFromBlockByHash(blockHash)
```
#### Parameters
`String` - The hash of the block to retrieve
#### Returns
`Object` -
- `number`: `Number` - The retrieved block's number
- `hash`: `String` - The retrieved block's hash
- `author`: `String` - The address of the block proposer
- `committers`: `[]String` - The list of all addresses whose seal appears in this block

View File

@ -921,7 +921,19 @@ web3._extend({
name: 'discard',
call: 'istanbul_discard',
params: 1
})
}),
new web3._extend.Method({
name: 'getSignersFromBlock',
call: 'istanbul_getSignersFromBlock',
params: 1,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
}),
new web3._extend.Method({
name: 'getSignersFromBlockByHash',
call: 'istanbul_getSignersFromBlockByHash',
params: 1
}),
],
properties:
[
@ -929,6 +941,10 @@ web3._extend({
name: 'candidates',
getter: 'istanbul_candidates'
}),
new web3._extend.Property({
name: 'nodeAddress',
getter: 'istanbul_nodeAddress'
}),
]
});
`