mirror of https://github.com/poanetwork/quorum.git
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:
parent
1dcee8518b
commit
66d91d0210
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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'
|
||||
}),
|
||||
]
|
||||
});
|
||||
`
|
||||
|
|
Loading…
Reference in New Issue