diff --git a/consensus/clique/api.go b/consensus/clique/api.go index 0cf25abff3..56c361ee27 100644 --- a/consensus/clique/api.go +++ b/consensus/clique/api.go @@ -31,7 +31,7 @@ type API struct { } // GetSnapshot retrieves the state snapshot at a given block. -func (api *API) GetSnapshot(number *rpc.BlockNumber) (interface{}, error) { +func (api *API) GetSnapshot(number *rpc.BlockNumber) (*snapshot, error) { // Retrieve the requested block number (or current if none requested) var header *types.Header if number == nil || *number == rpc.LatestBlockNumber { @@ -46,6 +46,15 @@ func (api *API) GetSnapshot(number *rpc.BlockNumber) (interface{}, error) { return api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) } +// GetSnapshotAtHash retrieves the state snapshot at a given block. +func (api *API) GetSnapshotAtHash(hash common.Hash) (*snapshot, error) { + header := api.chain.GetHeaderByHash(hash) + if header == nil { + return nil, errUnknownBlock + } + return api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) +} + // GetSigners retrieves the list of authorized signers at the specified block. func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) { // Retrieve the requested block number (or current if none requested) @@ -66,6 +75,19 @@ func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) { return snap.signers(), nil } +// GetSignersAtHash retrieves the state snapshot at a given block. +func (api *API) GetSignersAtHash(hash common.Hash) ([]common.Address, error) { + header := api.chain.GetHeaderByHash(hash) + if header == nil { + return nil, errUnknownBlock + } + snap, err := api.clique.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil) + if err != nil { + return nil, err + } + return snap.signers(), nil +} + // Proposals returns the current proposals the node tries to uphold and vote on. func (api *API) Proposals() map[common.Address]bool { api.clique.lock.RLock() diff --git a/consensus/clique/snapshot_test.go b/consensus/clique/snapshot_test.go index 3ebe33bc5d..49a1d7d5b3 100644 --- a/consensus/clique/snapshot_test.go +++ b/consensus/clique/snapshot_test.go @@ -78,6 +78,7 @@ func (r *testerChainReader) Config() *params.ChainConfig { panic func (r *testerChainReader) CurrentHeader() *types.Header { panic("not supported") } func (r *testerChainReader) GetHeader(common.Hash, uint64) *types.Header { panic("not supported") } func (r *testerChainReader) GetBlock(common.Hash, uint64) *types.Block { panic("not supported") } +func (r *testerChainReader) GetHeaderByHash(common.Hash) *types.Header { panic("not supported") } func (r *testerChainReader) GetHeaderByNumber(number uint64) *types.Header { if number == 0 { return core.GetHeader(r.db, core.GetCanonicalHash(r.db, 0), 0) diff --git a/consensus/consensus.go b/consensus/consensus.go index e318e57c01..c199e627fd 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -40,6 +40,9 @@ type ChainReader interface { // GetHeaderByNumber retrieves a block header from the database by number. GetHeaderByNumber(number uint64) *types.Header + // GetHeaderByHash retrieves a block header from the database by its hash. + GetHeaderByHash(hash common.Hash) *types.Header + // GetBlock retrieves a block from the database by hash and number. GetBlock(hash common.Hash, number uint64) *types.Block } diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index dd325100f4..ac79398b99 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -30,10 +30,8 @@ var Modules = map[string]string{ "shh": Shh_JS, "swarmfs": SWARMFS_JS, "txpool": TxPool_JS, - } - const Chequebook_JS = ` web3._extend({ property: 'chequebook', @@ -77,12 +75,22 @@ web3._extend({ params: 1, inputFormatter: [null] }), + new web3._extend.Method({ + name: 'getSnapshotAtHash', + call: 'clique_getSnapshotAtHash', + params: 1 + }), new web3._extend.Method({ name: 'getSigners', call: 'clique_getSigners', params: 1, inputFormatter: [null] }), + new web3._extend.Method({ + name: 'getSignersAtHash', + call: 'clique_getSignersAtHash', + params: 1 + }), new web3._extend.Method({ name: 'propose', call: 'clique_propose',