accounts: remove clique-specific signing method, replace with more generic

This commit is contained in:
Martin Holst Swende 2018-12-06 15:46:52 +01:00
parent 762482ef2c
commit bfa4fb0521
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
6 changed files with 74 additions and 17 deletions

View file

@ -91,7 +91,7 @@ type Wallet interface {
// chain state reader.
SelfDerive(base DerivationPath, chain ethereum.ChainStateReader)
// SignCliqueHeader requests the wallet to sign the hash of a given Clique header
// SignData requests the wallet to sign the hash of the given data
// It looks up the account specified either solely via its address contained within,
// or optionally with the aid of any location metadata from the embedded URL field.
//
@ -101,7 +101,7 @@ type Wallet interface {
// about which fields or actions are needed. The user may retry by providing
// the needed details via SignHashWithPassphrase, or by other means (e.g. unlock
// the account in a keystore).
SignCliqueHeader(account Account, header *types.Header) ([]byte, error)
SignData(account Account, mimeType string, data []byte) ([]byte, error)
// Signtext requests the wallet to sign the hash of a given piece of data, prefixed
// by the Ethereum prefix scheme

View file

@ -18,6 +18,7 @@ package external
import (
"fmt"
"github.com/ethereum/go-ethereum/crypto"
"math/big"
"sync"
@ -151,11 +152,11 @@ func (api *ExternalSigner) signHash(account accounts.Account, hash []byte) ([]by
return []byte{}, fmt.Errorf("operation not supported on external signers")
}
// SignCliqueHeader implements accounts.Wallet, attempting to sign the given clique header
func (api *ExternalSigner) SignCliqueHeader(account accounts.Account, header *types.Header) ([]byte, error) {
// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed
func (api *ExternalSigner) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) {
// TODO! Replace this with a call to clef SignData with correct mime-type for Clique, once we
// have that in place
return api.signHash(account, accounts.CliqueHash(header).Bytes())
return api.signHash(account, crypto.Keccak256(data))
}
func (api *ExternalSigner) SignText(account accounts.Account, text []byte) ([]byte, error) {

View file

@ -17,6 +17,7 @@
package keystore
import (
"github.com/ethereum/go-ethereum/crypto"
"math/big"
ethereum "github.com/ethereum/go-ethereum"
@ -91,9 +92,9 @@ func (w *keystoreWallet) signHash(account accounts.Account, hash []byte) ([]byte
return w.keystore.SignHash(account, hash)
}
// SignCliqueHeader implements accounts.Wallet, attempting to sign the given clique header
func (w *keystoreWallet) SignCliqueHeader(account accounts.Account, header *types.Header) ([]byte, error) {
return w.signHash(account, accounts.CliqueHash(header).Bytes())
// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed
func (w *keystoreWallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) {
return w.signHash(account, crypto.Keccak256(data))
}
func (w *keystoreWallet) SignText(account accounts.Account, text []byte) ([]byte, error) {

View file

@ -20,6 +20,7 @@ package usbwallet
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum/crypto"
"io"
"math/big"
"sync"
@ -501,9 +502,9 @@ func (w *wallet) signHash(account accounts.Account, hash []byte) ([]byte, error)
return nil, accounts.ErrNotSupported
}
// SignCliqueHeader implements accounts.Wallet, attempting to sign the given clique header
func (w *wallet) SignCliqueHeader(account accounts.Account, header *types.Header) ([]byte, error) {
return w.signHash(account, accounts.CliqueHash(header).Bytes())
// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed
func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) {
return w.signHash(account, crypto.Keccak256(data))
}
func (w *wallet) SignText(account accounts.Account, text []byte) ([]byte, error) {

View file

@ -20,6 +20,8 @@ package clique
import (
"bytes"
"errors"
"github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/rlp"
"math/big"
"math/rand"
"sync"
@ -136,7 +138,7 @@ var (
// SignerFn is a signer callback function to request a header to be signed by a
// backing account.
type SignerFn func(accounts.Account, *types.Header) ([]byte, error)
type SignerFn func(accounts.Account, string, []byte) ([]byte, error)
// ecrecover extracts the Ethereum account address from a signed header.
func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) {
@ -152,7 +154,7 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, er
signature := header.Extra[len(header.Extra)-extraSeal:]
// Recover the public key and the Ethereum address
pubkey, err := crypto.Ecrecover(accounts.CliqueHash(header).Bytes(), signature)
pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature)
if err != nil {
return common.Address{}, err
}
@ -613,7 +615,7 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, results c
log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle))
}
// Sign all the things!
sighash, err := signFn(accounts.Account{Address: signer}, header)
sighash, err := signFn(accounts.Account{Address: signer}, "application/x-clique-header", CliqueRLP(header))
if err != nil {
return err
}
@ -630,7 +632,7 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, results c
select {
case results <- block.WithSeal(header):
default:
log.Warn("Sealing result is not read by miner", "sealhash", c.SealHash(header))
log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header))
}
}()
@ -660,7 +662,31 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
// SealHash returns the hash of a block prior to it being sealed.
func (c *Clique) SealHash(header *types.Header) common.Hash {
return accounts.CliqueHash(header)
return SealHash(header)
}
// SealHash returns the hash of a block prior to it being sealed.
func SealHash(header *types.Header) (hash common.Hash) {
hasher := sha3.NewKeccak256()
rlp.Encode(hasher, []interface{}{
header.ParentHash,
header.UncleHash,
header.Coinbase,
header.Root,
header.TxHash,
header.ReceiptHash,
header.Bloom,
header.Difficulty,
header.Number,
header.GasLimit,
header.GasUsed,
header.Time,
header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
header.MixDigest,
header.Nonce,
})
hasher.Sum(hash[:0])
return hash
}
// Close implements consensus.Engine. It's a noop for clique as there are no background threads.
@ -678,3 +704,31 @@ func (c *Clique) APIs(chain consensus.ChainReader) []rpc.API {
Public: false,
}}
}
// CliqueRLP returns the rlp bytes which needs to be signed for the proof-of-authority
// sealing. The RLP to sign consists of the entire header apart from the 65 byte signature
// contained at the end of the extra data.
//
// Note, the method requires the extra data to be at least 65 bytes, otherwise it
// panics. This is done to avoid accidentally using both forms (signature present
// or not), which could be abused to produce different hashes for the same header.
func CliqueRLP(header *types.Header) []byte {
data, _ := rlp.EncodeToBytes([]interface{}{
header.ParentHash,
header.UncleHash,
header.Coinbase,
header.Root,
header.TxHash,
header.ReceiptHash,
header.Bloom,
header.Difficulty,
header.Number,
header.GasLimit,
header.GasUsed,
header.Time,
header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
header.MixDigest,
header.Nonce,
})
return data
}

View file

@ -432,7 +432,7 @@ func (s *Ethereum) StartMining(threads int) error {
log.Error("Etherbase account unavailable locally", "err", err)
return fmt.Errorf("signer missing: %v", err)
}
clique.Authorize(eb, wallet.SignCliqueHeader)
clique.Authorize(eb, wallet.SignData)
}
// If mining is started, we can disable the transaction rejection mechanism
// introduced to speed sync times.